并发下常见的加锁及锁的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下的权限算法的实现
Apr 28 PHP
PHP 命名空间实例说明
Jan 27 PHP
PHP+jQuery实现自动补全功能源码
May 15 PHP
深入Nginx + PHP 缓存详解
Jul 11 PHP
php统计时间和内存使用情况示例分享
Mar 13 PHP
浅析PHP中strlen和mb_strlen的区别
Aug 31 PHP
thinkphp浏览历史功能实现方法
Oct 29 PHP
php字符串分割函数用法实例
Mar 17 PHP
php简单socket服务器客户端代码实例
May 18 PHP
PHP内存使用情况如何获取
Oct 10 PHP
PDO::getAvailableDrivers讲解
Jan 28 PHP
PHP rsa加密解密算法原理解析
Dec 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获取百度收录、百度热词及百度快照的方法
2015/04/02 PHP
Laravel 加载第三方类库的方法
2018/04/20 PHP
又一个小巧的图片预加载类
2007/05/05 Javascript
setInterval 和 setTimeout会产生内存溢出
2008/02/15 Javascript
HTML中Select不用Disabled实现ReadOnly的效果
2008/04/07 Javascript
js添加table的行和列 具体实现方法
2013/07/22 Javascript
JS下拉缓冲菜单示例代码
2013/08/30 Javascript
javascript设计模式之中介者模式Mediator
2014/12/30 Javascript
浅谈javascript属性onresize
2015/04/20 Javascript
javascript原型继承工作原理和实例详解
2016/04/07 Javascript
详解Node.js模块间共享数据库连接的方法
2016/05/24 Javascript
Bootstrap CDN和本地化环境搭建
2016/10/26 Javascript
Angular-Ui-Router+ocLazyLoad动态加载脚本示例
2017/03/02 Javascript
jQuery实现动态给table赋值的方法示例
2017/07/04 jQuery
node+express+ejs使用模版引擎做的一个示例demo
2017/09/18 Javascript
vue 自定义组件 v-model双向绑定、 父子组件同步通信的多种写法
2017/11/27 Javascript
React Native 截屏组件的示例代码
2017/12/06 Javascript
Vue底层实现原理总结
2018/02/17 Javascript
微信小程序动态显示项目倒计时
2019/06/20 Javascript
JavaScript函数Call、Apply原理实例解析
2020/02/17 Javascript
element-ui树形控件后台返回的数据+生成组织树的工具类
2020/03/05 Javascript
Python使用while循环花式打印乘法表
2019/01/28 Python
pycharm配置git(图文教程)
2019/08/16 Python
深度学习入门之Pytorch 数据增强的实现
2020/02/26 Python
css3 给页面加个半圆形导航条主要利用旋转和倾斜样式
2014/02/10 HTML / CSS
5 个强大的HTML5 API 函数推荐
2014/11/19 HTML / CSS
LUISAVIAROMA中国官网:时尚奢侈品牌购物网站
2020/11/01 全球购物
竞聘书怎么写,如何写?
2014/03/31 职场文书
活动总结新闻稿
2014/08/30 职场文书
民警个人对照检查剖析材料
2014/09/17 职场文书
老公给老婆的检讨书(精华篇)
2014/10/18 职场文书
2014年社区工会工作总结
2014/12/18 职场文书
化妆品促销活动总结
2015/05/07 职场文书
Python下opencv库的安装过程及问题汇总
2021/06/11 Python
springboot新建项目pom.xml文件第一行报错的解决
2022/01/18 Java/Android
古见同学有交流障碍症 第二季宣传CM公开播出
2022/04/11 日漫