并发下常见的加锁及锁的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 相关文章推荐
利用文件属性结合Session实现在线人数统计
Oct 09 PHP
Can't create/write to file 'C:\WINDOWS\TEMP\...MYSQL报错解决方法
Jun 30 PHP
关于PHP的相似度计算函数:levenshtein的使用介绍
Apr 15 PHP
PHP获取MSN好友列表类的实现代码
Jun 23 PHP
php strrpos()与strripos()函数
Aug 31 PHP
php 模拟post_验证页面的返回状态(实例讲解)
Oct 28 PHP
php类声明和php类使用方法示例分享
Mar 29 PHP
使用php批量删除数据库下所有前缀为prefix_的表
Jun 09 PHP
ThinkPHP查询返回简单字段数组的方法
Aug 25 PHP
php的4种常见运行方式
Mar 20 PHP
Yii2实现跨mysql数据库关联查询排序功能代码
Feb 10 PHP
php闭包中使用use声明变量的作用域实例分析
Aug 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
POSIX 风格和兼容 Perl 风格两种正则表达式主要函数的类比(preg_match, preg_replace, ereg, ereg_replace)
2010/10/12 PHP
PHP与Java进行通信的实现方法
2013/10/21 PHP
PHP实现的回溯算法示例
2017/08/15 PHP
visual studio code 调试php方法(图文详解)
2017/09/15 PHP
PHP基于openssl实现的非对称加密操作示例
2019/01/11 PHP
Apply an AutoFormat to an Excel Spreadsheet
2007/06/12 Javascript
jQuery 1.5.1 发布,全面支持IE9 修复大量bug
2011/02/26 Javascript
js模拟点击事件实现代码
2012/11/06 Javascript
用js模拟struts2的多action调用示例
2014/05/19 Javascript
JavaScript匿名函数与委托使用示例
2014/07/22 Javascript
JS中产生20位随机数以0-9为例也可以是a-z A-Z
2014/08/01 Javascript
jQuery+ajax实现滚动到页面底部自动加载图文列表效果(类似图片懒加载)
2016/06/07 Javascript
JavaScript 是什么意思
2016/09/22 Javascript
实现JavaScript高性能的数据存储
2016/12/11 Javascript
JS点击缩略图整屏居中放大图片效果
2017/07/04 Javascript
JavaScript requestAnimationFrame动画详解
2017/09/14 Javascript
jQuery实现倒计时功能 jQuery实现计时器功能
2017/09/19 jQuery
vue-cli 自定义指令directive 添加验证滑块示例
2017/10/19 Javascript
JavaScript实现树的遍历算法示例【广度优先与深度优先】
2017/10/26 Javascript
nodeJS模块简单用法示例
2018/04/21 NodeJs
react组件从搭建脚手架到在npm发布的步骤实现
2019/01/09 Javascript
详解vue 2.6 中 slot 的新用法
2019/07/09 Javascript
Python的gevent框架的入门教程
2015/04/29 Python
Python获取二维矩阵每列最大值的方法
2018/04/03 Python
python3 常见解密加密算法实例分析【base64、MD5等】
2019/12/19 Python
python如何代码集体右移
2020/07/20 Python
python切割图片的示例
2020/11/12 Python
DRF使用simple JWT身份验证的实现
2021/01/14 Python
美国经典刺绣和字母儿童服装特卖:Smocked Auctions
2018/07/16 全球购物
贪睡宠物用品:Snoozer Pet Products
2020/02/04 全球购物
Android interview questions
2016/12/25 面试题
车间班长岗位职责
2013/11/30 职场文书
完整版商业计划书
2014/09/15 职场文书
普通员工辞职信范文
2015/05/12 职场文书
2015年骨干教师工作总结
2015/05/26 职场文书
ant design vue的form表单取值方法
2022/06/01 Vue.js