并发下常见的加锁及锁的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 相关文章推荐
递归列出所有文件和目录
Oct 09 PHP
通过文字传递创建的图形按钮
Oct 09 PHP
PHP获取http请求的头信息实现步骤
Dec 16 PHP
基于php设计模式中单例模式的应用分析
May 15 PHP
探讨PHP函数ip2long转换IP时数值太大产生负数的解决方法
Jun 06 PHP
使用PHP破解防盗链图片的一个简单方法
Jun 07 PHP
php强制更新图片缓存的方法
Feb 11 PHP
浅谈PHP中Stream(流)
Jun 08 PHP
iOS自定义提示弹出框实现类似UIAlertView的效果
Nov 16 PHP
浅谈PHP安全防护之Web攻击
Jan 03 PHP
PHP实现字符串翻转功能的方法【递归与循环算法】
Nov 03 PHP
thinkPHP框架实现的无限回复评论功能示例
Jun 09 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微信公众号开发之微信企业付款给个人
2018/10/04 PHP
PHP利用递归函数实现无限级分类的方法
2019/03/22 PHP
Javascript 遮罩层和加载效果代码
2013/08/01 Javascript
编写高效jQuery代码的4个原则和5个技巧
2014/04/24 Javascript
JavaScript模块随意拖动示例代码
2014/05/27 Javascript
jQuery实现点击图片翻页展示效果的方法
2015/02/16 Javascript
JS设置下拉列表框当前所选值的方法
2015/12/22 Javascript
莱鸟介绍window.print()方法
2016/01/06 Javascript
Seajs 简易文档 提供简单、极致的模块化开发体验
2016/04/13 Javascript
javascript中的 object 和 function小结
2016/08/14 Javascript
getElementById().innerHTML与getElementById().value的区别
2016/10/27 Javascript
underscore之Collections_动力节点Java学院整理
2017/07/10 Javascript
利用node.js实现自动生成前端项目组件的方法详解
2017/07/12 Javascript
浅谈Node Inspector 代理实现
2017/10/19 Javascript
Vue传参一箩筐(页面、组件)
2019/04/04 Javascript
[01:33]完美世界DOTA2联赛PWL S3 集锦第二期
2020/12/21 DOTA
python实现的简单抽奖系统实例
2015/05/22 Python
Python在线运行代码助手
2016/07/15 Python
Python 进程操作之进程间通过队列共享数据,队列Queue简单示例
2019/10/11 Python
基于python实现把图片转换成素描
2019/11/13 Python
tensorflow实现打印ckpt模型保存下的变量名称及变量值
2020/01/04 Python
解决jupyter运行pyqt代码内核重启的问题
2020/04/16 Python
python 爬虫如何正确的使用cookie
2020/10/27 Python
Python 转移文件至云对象存储的方法
2021/02/07 Python
利用HTML5画出一个坦克的形状具体实现代码
2013/06/20 HTML / CSS
JINS眼镜官方网站:日本最大的眼镜邮购
2016/10/14 全球购物
安全检查与奖惩制度
2014/01/23 职场文书
《风筝》教学反思
2014/04/10 职场文书
小学学雷锋活动总结
2014/04/25 职场文书
机械设计及其自动化专业求职信
2014/06/09 职场文书
小学阳光体育活动总结
2014/07/05 职场文书
班级团队活动方案
2014/08/14 职场文书
2015年小学数学教研组工作总结
2015/05/21 职场文书
篮球赛新闻稿
2015/07/17 职场文书
《初涉尘世》读后感3篇
2020/01/10 职场文书
HTML+CSS实现导航条下拉菜单的示例代码
2021/08/02 HTML / CSS