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


Posted in PHP onOctober 12, 2010

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

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

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

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

本类在孙立同学的类的基础上做了小点改进的了.具体可以看 http://code.google.com/p/phplock 感谢孙同学的分享精神!
PHP 相关文章推荐
PHP数据缓存技术
Feb 14 PHP
PHP 中的批处理的实现
Jun 14 PHP
PHP 5.0对象模型深度探索之对象复制
Mar 27 PHP
PHP UTF8编码内的繁简转换类
Jul 20 PHP
上传文件先创建目录 再上传到目录里面去
Dec 29 PHP
QQ登录 PHP OAuth示例代码
Jul 20 PHP
php中日期加减法运算实现代码
Dec 08 PHP
php 文本文件的读取效率
Feb 10 PHP
php+mysqli实现批量执行插入、更新及删除数据的方法
Jan 29 PHP
PHP生成及获取JSON文件的方法
Aug 23 PHP
yii2高级应用之自定义组件实现全局使用图片上传功能的方法
Oct 08 PHP
stripos函数知识点实例分享
Feb 11 PHP
PHP开发的一些注意点总结
Oct 12 #PHP
php更改目录及子目录下所有的文件后缀的代码
Sep 24 #PHP
比较全面的PHP数组的使用方法小结
Sep 23 #PHP
PHP之COOKIE支持详解
Sep 20 #PHP
PHPCMS的使用小结
Sep 20 #PHP
PHP中的MYSQL常用函数(php下操作数据库必备)
Sep 12 #PHP
zen cart新进商品的随机排序修改方法
Sep 10 #PHP
You might like
php实现天干地支计算器示例
2014/03/14 PHP
php自定义类fsocket模拟post或get请求的方法
2015/07/31 PHP
PHP概率计算函数汇总
2015/09/13 PHP
jquery插件 cluetip 关键词注释
2010/01/12 Javascript
jQuery 方法大全方便学习参考
2010/02/25 Javascript
使用jQuery不判断浏览器高度解决iframe自适应高度问题
2014/12/16 Javascript
每天一篇javascript学习小结(Function对象)
2015/11/16 Javascript
Web前端新人笔记之jquery入门心得(新手必看)
2016/05/17 Javascript
js动态添加的DIV中的onclick事件简单实例
2016/07/25 Javascript
jQuery命名空间与闭包用法示例
2017/01/12 Javascript
Node.js简单入门前传
2017/08/21 Javascript
jQuery图片缩放插件smartZoom使用实例详解
2017/08/25 jQuery
vue router自动判断左右翻页转场动画效果
2017/10/10 Javascript
js验证身份证号码记录的方法
2019/04/26 Javascript
JS简单数组排序操作示例【sort方法】
2019/05/17 Javascript
微信浏览器下拉黑边解决方案 wScroollFix
2020/01/21 Javascript
vue实现评价星星功能
2020/06/30 Javascript
解决vue项目input输入框双向绑定数据不实时生效问题
2020/08/05 Javascript
浅谈vue-props的default写不写有什么区别
2020/08/09 Javascript
jquery插件实现轮播图效果
2020/10/19 jQuery
Django中使用locals()函数的技巧
2015/07/16 Python
python各种语言间时间的转化实现代码
2016/03/23 Python
利用Python进行异常值分析实例代码
2017/12/07 Python
Python实现的将文件每一列写入列表功能示例【测试可用】
2018/03/19 Python
PYTHON基础-时间日期处理小结
2018/05/05 Python
python打印n位数“水仙花数”(实例代码)
2019/12/25 Python
python查找特定名称文件并按序号、文件名分行打印输出的方法
2020/04/24 Python
文秘个人求职信范文
2014/04/22 职场文书
学风建设演讲稿
2014/09/12 职场文书
关于随地扔垃圾的检讨书
2014/09/30 职场文书
学习三严三实心得体会
2014/10/13 职场文书
社区活动总结
2015/02/04 职场文书
七年级之开学家长寄语35句
2019/09/05 职场文书
SQL Server——索引+基于单表的数据插入与简单查询【1】
2021/04/05 SQL Server
Go标准容器之Ring的使用说明
2021/05/05 Golang
ROS系统将python包编译为可执行文件的简单步骤
2021/07/25 Python