PHP 5.3.8的互斥锁

时间:2012-01-05 15:19:18

标签: php mutex

我在运行Windows XP SP3和Apache 2.2.21的Web服务器上使用PHP 5.3.8,我需要创建一个互斥锁。经过一些研究,我遇到了flock命令,并按照以下方式实现:

class Mutex
{
    private $lock_ = null;

    // create a mutex with with a given id. This ID must be system unique.
    // [string] id - a unique id
    // return - true on success
    public function Initialize($id)
    {
        $this->lock_ = fopen($id, 'a');
        return is_resource($this->lock_);
    }

    // destroy the mutex
    public function Destroy()
    {
        $result = false;
        if (is_resource($this->lock_));
        {
            $result = flock($this->lock_, LOCK_UN);
            $result &= fclose($this->lock_);
            $this->lock_ = null;
        }
        return $result;
    }

    // exclusively lock the resource
    // return - true on success
    public function Lock()
    {
        if (is_resource($this->lock_))
            return flock($this->lock_, LOCK_EX);
        return false;
    }

    // release the locked resource
    // return - true on success
    public function Release()
    {
        if (is_resource($this->lock_))
            return flock($this->lock_, LOCK_UN);
        return false;
    }
}

但是,当我去使用这个课时:

$this->cache_lock_ = new Mutex();
$this->cache_lock_->Initialize("e:\\cache_lock");

if ($this->cache_lock_->Lock())
    echo "Acquired 1 ".PHP_EOL;
if ($this->cache_lock_->Lock())
    echo "Acquired 2 ".PHP_EOL;
$this->cache_lock_->Release();

$this->cache_lock_->Destroy();

我看到Acquired 1 Acquired 2已打印,表明锁已被获取两次,尽管我指定它是独占的。

有人能说出我做错了吗?理想情况下,我希望第二个Lock()调用toblock直到资源可用。

谢谢, PaulH

1 个答案:

答案 0 :(得分:5)

在同一个文件句柄上调用flock()两次将返回true并且不会阻塞,因为该函数检查文件句柄是否已被锁定,如果是,则返回true。这是预期的行为。但是,如果多个进程并行运行,它将按预期工作,因为每个进程将具有不同的文件句柄。如果要在单个进程中对此进行测试,请为同一文件对象创建多个句柄:

$a = new Mutex();
$a->Initialize("file.lock");
$a->Lock(); // this will simply lock the file object
$b = new Mutex();
$b->Initialize("file.lock");
$b->Lock(); // this will block, because the file is locked by $a