即时通讯使用http://www.tuxradar.com/practicalphp/8/11/0 这样的简单测试脚本
<?php
$fp = fopen("foo.txt", "w");
if (flock($fp, LOCK_EX)) {
print "Got lock!\n";
sleep(10);
flock($fp, LOCK_UN);
}
Run Code Online (Sandbox Code Playgroud)
我打开了5个shell并一个接一个地执行脚本脚本阻塞,直到锁定被释放,然后在释放后继续
即时通讯不是真的在php中填充,但我的问题是:谁知道flock()的获取顺序?
e.g.
t0: process 1 lock's
t1: process 2 try_lock < blocking
t2: process 3 try_lock < blocking
t3: process 1 releases lock
t4: ?? which process get's the lock?
Run Code Online (Sandbox Code Playgroud)
是否有一个简单的确定性顺序,如队列或内核"只是"通过"更高级的规则"选择一个?
如果有多个进程在等待独占锁定,则不会指定哪个进程首先成功获取它.不要依赖任何特定的订购.
话虽如此,当前内核代码按照它们阻止的顺序唤醒它们.此评论位于fs/locks.c:
/* Insert waiter into blocker's block list.
* We use a circular list so that processes can be easily woken up in
* the order they blocked. The documentation doesn't require this but
* it seems like the reasonable thing to do.
*/
Run Code Online (Sandbox Code Playgroud)
如果要按顺序运行一组进程,请不要使用flock().使用SysV信号量(semget()/ semop()).
创建一个信号量集,其中包含每个进程在第一个之后的一个信号量,并将它们全部初始化为-1.对于第一个之后的每个进程,semop()在该进程的信号量上执行sem_op值为零 - 这将阻止它.在第一个过程完成后,它应该semop()对第二个进程的信号量执行一个sem_op值为1的操作 - 这将唤醒第二个进程.在第二个过程完成后,它应该semop()在第三个进程的信号量上执行sem_op值为1的操作,依此类推.