zl程序教程

您现在的位置是:首页 >  后端

当前栏目

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

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

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

使用如下:
$lock=newCacheLock("key_name");
$lock->lock();
//logichere
$lock->unlock();
//使用过程中需要注意下文件锁所在路径需要有写权限.
具体类如下:
复制代码代码如下:

<?php
/**
*CacheLock进程锁,主要用来进行cache失效时的单进程cache获取,防止过多的SQL请求穿透到数据库
*用于解决PHP在并发时候的锁控制,通过文件/eaccelerator进行进程间锁定
*如果没有使用eaccelerator则进行进行文件锁处理,会做对应目录下产生对应粒度的锁
*使用了eaccelerator则在内存中处理,性能相对较高
*不同的锁之间并行执行,类似mysqlinnodb的行级锁
*本类在sunli的phplock的基础上做了少许修改http://code.google.com/p/phplock
*@authoryangxinqi
*
*/
classCacheLock
{
//文件锁存放路径
private$path=null;
//文件句柄
private$fp=null;
//锁粒度,设置越大粒度越小
private$hashNum=100;
//cachekey
private$name;
//是否存在eaccelerator标志
private$eAccelerator=false;
/**
*构造函数
*传入锁的存放路径,及cachekey的名称,这样可以进行并发
*@paramstring$path锁的存放目录,以"/"结尾
*@paramstring$namecachekey
*/
publicfunction__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封装
*@paramint$string
*@returnint
*/
privatefunction_mycrc32($string)
{
$crc=abs(crc32($string));
if($crc&0x80000000){
$crc^=0xffffffff;
$crc+=1;
}
return$crc;
}
/**
*加锁
*Enterdescriptionhere...
*/
publicfunctionlock()
{
//如果无法开启ea内存锁,则开启文件锁
if(!$this->eAccelerator)
{
//配置目录权限可写
$this->fp=fopen($this->path,"w+");
if($this->fp===false)
{
returnfalse;
}
returnflock($this->fp,LOCK_EX);
}else{
returneaccelerator_lock($this->name);
}
}
/**
*解锁
*Enterdescriptionhere...
*/
publicfunctionunlock()
{
if(!$this->eAccelerator)
{
if($this->fp!==false)
{
flock($this->fp,LOCK_UN);
clearstatcache();
}
//进行关闭
fclose($this->fp);
}else{
returneaccelerator_unlock($this->name);
}
}
}

本类在孙立同学的类的基础上做了小点改进的了.具体可以看http://code.google.com/p/phplock感谢孙同学的分享精神!