【发布时间】:2013-03-13 08:26:43
【问题描述】:
我想使用排他/共享的阻塞和非阻塞锁,就像flock() 中的这些锁一样。如何使用信号量来实现这一点?
【问题讨论】:
我想使用排他/共享的阻塞和非阻塞锁,就像flock() 中的这些锁一样。如何使用信号量来实现这一点?
【问题讨论】:
这取决于用例。
如果您只在一台服务器上,请使用锁定文件。
function doSomething() {
$file = /temp/path/somthing.lock;
if (file_exists($file)) {
return false;
}
touch($file);
// Safely mess with things
unlink($file);
}
如果您有多个 Web 服务器,例如在负载均衡器后面,同样的事情可以通过在 mysql 中使用表来完成。
function doSomething() {
$query = "SELECT * FROM locks WHERE name='something'");
$res = mysqli_query($query);
if (mysql_num_rows($res) > 0) {
return false;
}
$query = "INSERT INTO locks (name) VALUES ('something')";
mysqli_query($query);
// Safely mess with things
$query = "DELETE FROM locks WHERE name='something'");
mysqli_query($query);
}
Memcache 是另一个具有多机支持的明显候选对象。
您不应使用 ACP,因为它仅用于缓存。这意味着您无法控制 ACP 存储何时被删除,它可能随时发生。
您也可以使用信号量,但是如果您使用多个服务器,则需要注意与锁定文件相同的注意事项。
我建议创建 lock($key)、is_locked($key) 和 release($key) 函数,然后在整个项目中认真地使用它们。这样您就可以从锁定文件开始(快速实现),然后在不编辑其余代码的情况下升级到更好的东西。如果您想真正花哨,可以将它们实现为记录器对象的方法,并将其放在代码的已知位置。
【讨论】:
locks.name 上有一个唯一索引,并且第一个可以成功创建记录的客户端持有锁。任何进一步的请求都将导致重复键错误。