使用共享内存实现php Spinlock
时间:2011-07-15
来源:互联网
本文使用共享内存方式实现一个属于php的“自旋锁(Spinlock)”。
主要特点:
1、检测和避免死锁
2、并可以自定义锁定超时
3、可以在运行结束后自动释放锁定
4、可搜集分析锁竞争和锁等待情况
复制代码
运行上述例子,测试同步情况:
在两个浏览器打开运行这个代码,分别输出,
浏览器1:
Start:13:07:19,Stop:13:07:22
浏览器2:
Start:13:07:19,Stop:13:07:25
第一个浏览器显示程序运行了3秒后结束。
第二个浏览器等待3秒后开始运行,总共耗时6秒,测试通过。
主要特点:
1、检测和避免死锁
2、并可以自定义锁定超时
3、可以在运行结束后自动释放锁定
4、可搜集分析锁竞争和锁等待情况
- <?php
- /**
- * php"自旋锁"功能 (PHP Spinlocks)
- * 用于php进程同步时使用
- *
- * Author : lajabs.net 2011/7/15
- */
-
- class slock
- {
- /**
- * $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;
- private $lock_timeout = 200;
- private $lock_wait_func;
- private $add_func;
- private $del_func;
- 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();
- }
-
-
-
-
- /*================================= 分割线 ==========================*/
-
-
-
- /**
- * 清除当前所有设置的锁,在当前的php进程中可以设置多个锁
- */
- public function clean()
- {
- if($this->locks)
- {
- foreach($this->locks as $lock => $tmp)
- call_user_func($this->del_func ,$lock);
- $this->locks = null;
- }
- }
-
-
-
- /**
- * 新建立一个锁
- * 首先会判断锁定标志是否已经定义,如果已锁定则判定为死锁
- * 其次使用apc共享内存方式add一个锁标志,如果失败则进入等待时间,直到超时
- */
- public function lock($mutex)
- {
- if($this->locks[$mutex]!=null)
- {
- throw new Exception('Detected deadlock.');
- return false;
- }
-
- while(call_user_func($this->add_func ,$mutex) == false)
- {
- ++$i;
- if($i > $this->lock_timeout)
- {
- throw new Exception('lock timeout.');
- return false;
- }
- call_user_func($this->lock_wait_func);
- }
- $this->locks[$mutex] = 1;
- return $mutex;
- }
-
-
- /**
- * 手动释放锁,一般不用,
- * 在当前对象析构时会自动释放所有锁
- */
- public function release($mutex)
- {
- if($mutex == false) return false;
- unset($this->locks[$mutex]);
- call_user_func($this->del_func ,$mutex);
- return true;
- }
- }
-
-
- /*
- Example:
-
- $lock = new slock();
- echo 'Start:',date('H:m:s'),',';
- $lock->lock(123);
- sleep(3);
- echo 'Stop:',date('H:m:s');
- //$lock->release(123);
- */
- ?>
在两个浏览器打开运行这个代码,分别输出,
浏览器1:
Start:13:07:19,Stop:13:07:22
浏览器2:
Start:13:07:19,Stop:13:07:25
第一个浏览器显示程序运行了3秒后结束。
第二个浏览器等待3秒后开始运行,总共耗时6秒,测试通过。
作者: bs 发布时间: 2011-07-15
作者: iap_spring 发布时间: 2011-07-15
apc没办法支持分布式吧,意义不太大,直接memcached
作者: lkm1107 发布时间: 2011-07-15
apc没办法支持分布式吧,意义不太大,直接memcached
lkm1107 发表于 2011-7-15 16:34
lkm1107 发表于 2011-7-15 16:34
适应重口味的,换成memcache端,改三行代码
-
- ...
- public function __construct()
- {
- $memcache_obj = memcache_connect("localhost", 11211);
- $this->add_func = function($mutex) use ($memcache_obj)
- {
- return memcache_add($memcache_obj, 'sl:'.$mutex, 1, false, 5);
- //return apc_add('sl:'.$mutex,1,5);
- };
-
- $this->del_func = function($mutex) use ($memcache_obj)
- {
- return memcache_delete($memcache_obj, 'sl:'.$mutex); //return apc_delete('sl:'.$mutex);
- };
-
- $this->lock_wait_func = function()
- {
- usleep(mt_rand(10000,50000));
- };
- }
- ...
作者: bs 发布时间: 2011-07-15
相关阅读 更多
热门阅读
-
office 2019专业增强版最新2021版激活秘钥/序列号/激活码推荐 附激活工具
阅读:74
-
如何安装mysql8.0
阅读:31
-
Word快速设置标题样式步骤详解
阅读:28
-
20+道必知必会的Vue面试题(附答案解析)
阅读:37
-
HTML如何制作表单
阅读:22
-
百词斩可以改天数吗?当然可以,4个步骤轻松修改天数!
阅读:31
-
ET文件格式和XLS格式文件之间如何转化?
阅读:24
-
react和vue的区别及优缺点是什么
阅读:121
-
支付宝人脸识别如何关闭?
阅读:21
-
腾讯微云怎么修改照片或视频备份路径?
阅读:28