+ -
当前位置:首页 → 问答吧 → 使用共享内存实现php Spinlock

使用共享内存实现php Spinlock

时间:2011-07-17

来源:互联网

本文使用共享内存方式实现一个属于php的“自旋锁(Spinlock)”。
主要特点:
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秒,测试通过。

作者: 693696817   发布时间: 2011-07-17

哈哈,又沙发,谢谢啦~!

作者: yjqwyc   发布时间: 2011-07-17

热门下载

更多