PHP flock函数与系统消息队列的关系!?
时间:2013-05-10
来源:互联网
本人在开发过程中用到了文件锁flock函数
然后又加了个C扩展调用一个C扩展与一个C服务端连接
(比如向系统消息队列发消息,另外一个客户端会去取这些消息)
该C服务端会使用系统的消息队列
在测试过程中会出现这样一种情况
当取消息的客服端停掉后不再取消息
等消息队列的消息数满后
PHP的flock函数就会出现阻塞,无法锁定,导致程序无法执行
这个问题不知道是不是与消息队列有关系,为什么有关系
本人水平有限,不知道怎么查,不知哪位高手遇到此种情况
作者: 除美灭日平韩 发布时间: 2013-05-10
作者: spser 发布时间: 2013-05-10
我把代码放出来吧,里面有个内存锁但是WEB模式与CLI模式不能共享内存
导致该锁无效,也帮忙看看
作者: 除美灭日平韩 发布时间: 2013-05-10
<?php class Cachelock { /** * $lock_timeout 设置等待回旋次数 * $lock_wait_func 设置等待机制,本例使用usleep+mt_rand随机等待,随机等待有利错开多个竞争 * $add_func 这里设置添加锁标志机制,本例使用PHP的APC组件apc_add函数,apc_add设定锁占有上限为5s,避免永久占有 * $del_func 这里设置删除锁标志机制,本例使用PHP的APC组件apc_delete函数 */ private $locks = array(); private $lock_timeout = 200; private $lock_wait_func; private $add_func; private $del_func; private $mutex =0; private $shmid = null; //文件锁存放路径 private $path = null; //文件句柄 private $fp = null; //锁粒度,设置越大粒度越小 private $hashNum = 100; //cache key private $name; /** * * 内存锁与文件锁的开关 * @var bool */ public $is_memory=FALSE; public function __construct() { // $this->add_func = function($mutex) // { // return apc_add('sl:'.$mutex,1,5); // }; // // $this->del_func = function($mutex) // { // return apc_delete('sl:'.$mutex); // }; // // $this->lock_wait_func = function() // { // usleep(mt_rand(10000,50000)); // }; } public function __destruct() { $this->clean(); } public function add_func(){ if(shm_has_var($this->shmid,$this->mutex)){ return FALSE; } return shm_put_var($this->shmid,$this->mutex,1); } public function del_func() { return shm_remove_var($this->shmid,$this->mutex); } /** * * 创建共享内存 */ public function cls_shm($mutex=''){ if($mutex){ $this->mutex = $this->_mycrc32($mutex); } if(!$this->shmid && $this->mutex){ $this->shmid = shm_attach( $this->mutex, $this->memsize, $this->perm ); // 创建一个共享内存 } } /** * 清除当前所有设置的锁,在当前的php进程中可以设置多个锁 */ public function clean() { if($this->is_memory){ if($this->locks) { foreach($this->locks as $lock => $tmp) $this->del_func($lock); $this->locks = array(); } shm_remove($this->shmid); } } /** * 新建立一个锁 * 首先会判断锁定标志是否已经定义,如果已锁定则判定为死锁 * 其次使用apc共享内存方式add一个锁标志,如果失败则进入等待时间,直到超时 */ public function lock($mutex,$path='') { if($this->is_memory){ //初始化 $this->cls_shm($mutex); if(isset($this->locks[$this->mutex]) && $this->locks[$this->mutex]!=null) { return false; } while($this->add_func() == false) { usleep(mt_rand(10000,50000)); } $this->locks[$this->mutex] = 1; return $this->mutex; }else{ //$this->path = $path.($this->_mycrc32($mutex) % $this->hashNum).'.txt'; $this->path = $path.$mutex.'.txt'; $this->name = $mutex; //配置目录权限可写 $this->fp = fopen($this->path,'a'); if($this->fp === false) { return false; } return flock($this->fp, LOCK_EX|LOCK_NB); } } /** * 手动释放锁,一般不用, * 在当前对象析构时会自动释放所有锁 */ public function release($mutex) { if($mutex == false) return false; if($this->is_memory){ unset($this->locks[$this->mutex]); $this->del_func(); return true; }else{ if($this->fp !== false) { flock($this->fp, LOCK_UN); clearstatcache(); } //进行关闭 fclose($this->fp); } } /** * crc32 * crc32封装 * @param int $string * [url=home.php?mod=space&uid=987628]@Return[/url] int */ private function _mycrc32($string) { $crc = abs (crc32($string)); if ($crc & 0x80000000) { $crc ^= 0xffffffff; $crc += 1; } return $crc; } } ?>
作者: 除美灭日平韩 发布时间: 2013-05-10
if ($this->cachelock->lock('lock')){
......................
$this->cachelock->release('lock');
}
作者: 除美灭日平韩 发布时间: 2013-05-10
return flock($this->fp, LOCK_EX|LOCK_NB);
加个日志追踪. 它锁的同时可能也有并发锁, 需要监控. 写入建议不要用LOCK_NB, 让它堵塞吧,
作者: spser 发布时间: 2013-05-10
作者: 除美灭日平韩 发布时间: 2013-05-10
作者: 除美灭日平韩 发布时间: 2013-05-10
那的确是flock被并发了.
php版本是多少? 升到新版试试.
linux不应该发生这种事才对的.
作者: spser 发布时间: 2013-05-10
这样看看会不会卡住.
作者: spser 发布时间: 2013-05-10
flock($this->fp, LOCK_EX);
这样看看会不会卡住.
会的,加不加LOCK_NB都会卡住
作者: 除美灭日平韩 发布时间: 2013-05-10
热门阅读
-
office 2019专业增强版最新2021版激活秘钥/序列号/激活码推荐 附激活工具
阅读:74
-
如何安装mysql8.0
阅读:31
-
Word快速设置标题样式步骤详解
阅读:28
-
20+道必知必会的Vue面试题(附答案解析)
阅读:37
-
HTML如何制作表单
阅读:22
-
百词斩可以改天数吗?当然可以,4个步骤轻松修改天数!
阅读:31
-
ET文件格式和XLS格式文件之间如何转化?
阅读:24
-
react和vue的区别及优缺点是什么
阅读:121
-
支付宝人脸识别如何关闭?
阅读:21
-
腾讯微云怎么修改照片或视频备份路径?
阅读:28