• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

并发下常见的加锁及锁的PHP具体实现代码_php技巧

php 搞代码 4年前 (2022-01-26) 12次浏览 已收录 0个评论

在最近的项目中有这样的场景
1.生成文件的时候,由于多用户都有权限进行生成,防止并发下,导致生成的结果出现错误,需要对生成的过程进行加锁,只容许一个用户在一个时间内进行操作,这个时候就需要用到锁了,将这个操作过程锁起来.
2.在用了cache的时候,cache失效可能导致瞬间的多数并发请求穿透到数据库此时也可以得需要用锁在同一并发的过程中将这个操作锁定.

针对以上的2种情况,现在的解决方法是对处理过程进行锁机制,通过PHP实现如下
用到了Eaccelerator的内存锁 和 文件锁,原理如下
判断系统中是否安了EAccelerator 如果有则使用内存锁,如果不存在,则进行文件锁
根据带入的key的不同可以实现多个锁直接的并行处理,类似Innodb的行级锁

使用如下:
$lock = new CacheLock(‘key_name’);
$lock->lock();
//logic here
$lock->unlock();
//使用过程中需要注意下文件锁所在路径需要有写权限.
具体类如下:

 <BR><?php <BR>/** <BR>* CacheLock 进程锁,主要用来进行cache失效时的单进程cache获取,防止过多的SQL请求穿透到数据库 <BR>* 用于解决PHP在并发时候的锁控制,通过文件/eaccelerator进行进程间锁定 <BR>* 如果没有使用eaccelerator则进行进行文件锁处理,会做对应目录下产生对应粒度的锁 <BR>* 使用了eaccelerator则在内存中处理,性能相对较高 <BR>* 不同的锁之间并行执行,类似mysql innodb的行级锁 <BR>* 本类在sunli的phplock的基础上做了少许修改 http://code.google.com/p/phplock <BR>* @author yangxinqi <BR>* <BR>*/ <BR>class CacheLock <BR>{ <BR>//文件锁存放路径 <BR>private $path = null; <BR>//文件句柄 <BR>private $fp = null; <BR>//锁粒度,设置越大粒度越小 <BR>private $hashNum = 100; <BR>//cache key <BR>private $name; <BR>//是否存在eaccelerator标志 <BR>private $eAccelerator = false; <BR>/** <BR>* 构造函数 <BR>* 传入锁的存放路径,及cache key的名称,这样可以进行并发 <BR>* @param string $path 锁的存放目录,以"/"结尾 <BR>* @param string $name cache key <BR>*/ <BR>public function __construct($name,$path='lock\\') <BR>{ <BR>//判断是否存在eAccelerator,这里启用了eAccelerator之后可以进行内存锁提高效率 <BR>$this->eAccelerator = function_exists("eaccelerator_lock"); <BR>if(!$this->eAccelerator) <BR>{ <BR>$this->path = $path.($this->_mycrc32($name) % $this->hashNum).'.txt'; <BR>} <BR>$this->name = $name; <BR>} <BR>/** <BR>* crc32 <BR>* crc32封装 <BR>* @param int $string <BR>* @return int <BR>*/ <BR>private function _mycrc32($string) <BR>{ <BR>$crc = ab<strong>*本文来源gaodai#ma#com搞@代~码^网+</strong><strong>搞代gaodaima码</strong>s (crc32($string)); <BR>if ($crc & 0x80000000) { <BR>$crc ^= 0xffffffff; <BR>$crc += 1; <BR>} <BR>return $crc; <BR>} <BR>/** <BR>* 加锁 <BR>* Enter description here ... <BR>*/ <BR>public function lock() <BR>{ <BR>//如果无法开启ea内存锁,则开启文件锁 <BR>if(!$this->eAccelerator) <BR>{ <BR>//配置目录权限可写 <BR>$this->fp = fopen($this->path, 'w+'); <BR>if($this->fp === false) <BR>{ <BR>return false; <BR>} <BR>return flock($this->fp, LOCK_EX); <BR>}else{ <BR>return eaccelerator_lock($this->name); <BR>} <BR>} <BR>/** <BR>* 解锁 <BR>* Enter description here ... <BR>*/ <BR>public function unlock() <BR>{ <BR>if(!$this->eAccelerator) <BR>{ <BR>if($this->fp !== false) <BR>{ <BR>flock($this->fp, LOCK_UN); <BR>clearstatcache(); <BR>} <BR>//进行关闭 <BR>fclose($this->fp); <BR>}else{ <BR>return eaccelerator_unlock($this->name); <BR>} <BR>} <BR>} <BR>


本类在孙立同学的类的基础上做了小点改进的了.具体可以看 http://code.google.com/p/phplock 感谢孙同学的分享精神!


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:并发下常见的加锁及锁的PHP具体实现代码_php技巧
喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址