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















