并发下常见的加锁及锁的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中cookies使用指南
Mar 16 PHP
一步一步学习PHP(6) 面向对象
Feb 16 PHP
判断PHP数组是否为空的代码
Sep 08 PHP
国外十大最流行的PHP框架排名
Jul 04 PHP
PHP判断文章里是否有图片的简单方法
Jul 26 PHP
THINKPHP支持YAML配置文件的设置方法
Mar 17 PHP
Yii中CGridView禁止列排序的设置方法
Jul 12 PHP
Netbeans 8.2与PHP相关的新特性介绍
Oct 08 PHP
php实现替换手机号中间数字为*号及隐藏IP最后几位的方法
Nov 16 PHP
PHP实现二维数组中的查找算法小结
Jun 09 PHP
php微信开发之关注事件
Jun 14 PHP
PHP+iframe模拟Ajax上传文件功能示例
Jul 02 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
星际争霸任务指南——神族
2020/03/04 星际争霸
十天学会php(2)
2006/10/09 PHP
检测png图片是否完整的php代码
2010/09/06 PHP
php提示undefined index的几种解决方法
2012/05/21 PHP
php生成局部唯一识别码LUID的代码
2012/10/06 PHP
php生成txt文件标题及内容的方法
2014/01/16 PHP
php计算给定时间之前的函数用法实例
2015/04/03 PHP
PHP内核学习教程之php opcode内核实现
2016/01/27 PHP
HR vs ForZe BO3 第二场 2.13
2021/03/10 DOTA
XRegExp 0.2: Now With Named Capture
2007/11/30 Javascript
js鼠标点击图片实现随机变换图片的方法
2015/02/16 Javascript
原生js结合html5制作小飞龙的简易跳球
2015/03/30 Javascript
jQuery Real Person验证码插件防止表单自动提交
2015/11/06 Javascript
jQuery 1.9.1源码分析系列(十五)之动画处理
2015/12/03 Javascript
JS拖拽组件学习使用
2016/01/19 Javascript
浅谈jQuery before和insertBefore的区别
2016/12/04 Javascript
Angularjs中ng-repeat-start与ng-repeat-end的用法实例介绍
2016/12/31 Javascript
基于vue实现swipe分页组件实例
2017/05/25 Javascript
浅谈es6 javascript的map数据结构
2017/12/14 Javascript
详解微信小程序缓存--缓存时效性
2019/05/02 Javascript
layui使用form表单实现post请求页面跳转的方法
2019/09/14 Javascript
Python os模块中的isfile()和isdir()函数均返回false问题解决方法
2015/02/04 Python
Python最长公共子串算法实例
2015/03/07 Python
剖析Python的Twisted框架的核心特性
2016/05/25 Python
Python多线程处理实例详解【单进程/多进程】
2019/01/30 Python
pow在python中的含义及用法
2019/07/11 Python
Python中的sys.stdout.write实现打印刷新功能
2020/02/21 Python
200行python代码实现贪吃蛇游戏
2020/04/24 Python
canvas 橡皮筋式线条绘图应用方法
2019/02/13 HTML / CSS
HTML5给汉字加拼音收起展开组件的实现代码
2020/04/08 HTML / CSS
公积金单位接收函
2014/01/11 职场文书
食品厂厂长岗位职责
2014/01/30 职场文书
厉行勤俭节约倡议书
2014/05/16 职场文书
2016年3月份红领巾广播稿
2015/12/21 职场文书
pytorch实现线性回归以及多元回归
2021/04/11 Python
python中的装饰器该如何使用
2021/06/18 Python