免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3319 | 回复: 0

使用共享内存实现php Spinlock [复制链接]

论坛徽章:
0
发表于 2011-07-15 14:06 |显示全部楼层
本文使用共享内存方式实现一个属于php的“自旋锁(Spinlock)”。
主要特点:
1、检测和避免死锁
2、并可以自定义锁定超时
3、可以在运行结束后自动释放锁定
4、可搜集分析锁竞争和锁等待情况

  1. <?php
  2. /**
  3. * php"自旋锁"功能 (PHP Spinlocks)
  4. * 用于php进程同步时使用
  5. *
  6. * Author : lajabs.net 2011/7/15
  7. */

  8. class slock
  9. {
  10.         /**
  11.          * $lock_timeout 设置等待回旋次数
  12.          * $lock_wait_func 设置等待机制,本例使用usleep+mt_rand随机等待,随机等待有利错开多个竞争
  13.          * $add_func 这里设置添加锁标志机制,本例使用PHP的APC组件apc_add函数,apc_add设定锁占有上限为5s,避免永久占有
  14.          * $del_func 这里设置删除锁标志机制,本例使用PHP的APC组件apc_delete函数
  15.          */
  16.         private $locks;
  17.         private $lock_timeout = 200;
  18.         private $lock_wait_func;
  19.         private $add_func;
  20.         private $del_func;
  21.         public function __construct()
  22.         {
  23.                 $this->add_func = function($mutex)
  24.                 {
  25.                         return apc_add('sl:'.$mutex,1,5);
  26.                 };

  27.                 $this->del_func = function($mutex)
  28.                 {
  29.                         return apc_delete('sl:'.$mutex);
  30.                 };

  31.                 $this->lock_wait_func = function()
  32.                 {
  33.                         usleep(mt_rand(10000,50000));
  34.                 };
  35.         }

  36.         public function __destruct()
  37.         {
  38.                 $this->clean();
  39.         }
  40.        



  41.         /*================================= 分割线 ==========================*/



  42.         /**
  43.          * 清除当前所有设置的锁,在当前的php进程中可以设置多个锁
  44.          */
  45.         public function clean()
  46.         {
  47.                 if($this->locks)
  48.                 {
  49.                         foreach($this->locks as $lock => $tmp)
  50.                                 call_user_func($this->del_func ,$lock);
  51.                         $this->locks = null;
  52.                 }
  53.         }



  54.         /**
  55.          * 新建立一个锁
  56.          * 首先会判断锁定标志是否已经定义,如果已锁定则判定为死锁
  57.          * 其次使用apc共享内存方式add一个锁标志,如果失败则进入等待时间,直到超时
  58.          */
  59.         public function lock($mutex)
  60.         {
  61.                 if($this->locks[$mutex]!=null)
  62.                 {
  63.                         throw new Exception('Detected deadlock.');
  64.                         return false;
  65.                 }

  66.                 while(call_user_func($this->add_func ,$mutex) == false)
  67.                 {
  68.                         ++$i;
  69.                         if($i > $this->lock_timeout)
  70.                         {
  71.                                 throw new Exception('lock timeout.');
  72.                                 return false;
  73.                         }
  74.                         call_user_func($this->lock_wait_func);
  75.                 }
  76.                 $this->locks[$mutex] = 1;
  77.                 return $mutex;
  78.         }


  79.         /**
  80.          * 手动释放锁,一般不用,
  81.          * 在当前对象析构时会自动释放所有锁
  82.          */
  83.         public function release($mutex)
  84.         {
  85.                 if($mutex == false) return false;
  86.                 unset($this->locks[$mutex]);
  87.                 call_user_func($this->del_func ,$mutex);
  88.                 return true;
  89.         }
  90. }


  91. /*
  92. Example:

  93. $lock = new slock();
  94. echo 'Start:',date('H:m:s'),',';
  95. $lock->lock(123);
  96. sleep(3);
  97. echo 'Stop:',date('H:m:s');
  98. //$lock->release(123);
  99. */
  100. ?>
复制代码
运行上述例子,测试同步情况:
在两个浏览器打开运行这个代码,分别输出,
浏览器1:
Start:13:07:19,Stop:13:07:22
浏览器2:
Start:13:07:19,Stop:13:07:25

第一个浏览器显示程序运行了3秒后结束。
第二个浏览器等待3秒后开始运行,总共耗时6秒,测试通过。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP