мьютекс с 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() блокировать до тех пор, пока ресурс не будет доступен.
Спасибо, ПаулЬ
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