мьютекс с PHP 5.3.8


Я использую PHP 5.3.8 на веб-сервере под управлением Windows XP SP3 и Apache 2.2.21, где мне нужно создать мьютекс. После некоторых исследований я наткнулся на команду 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() блокировать до тех пор, пока ресурс не будет доступен.

Спасибо, ПаулЬ

 2
Author: PaulH, 2012-01-05

1 answers

Вызов 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
 5
Author: kuba, 2012-01-05 15:39:32