3

我使用来自 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);
}

我打开了 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?

是否有一个简单的确定性顺序,例如队列,或者内核“只是”通过“更高级的规则”选择一个?

4

1 回答 1

8

如果有多个进程在等待一个独占锁,则不指定哪个进程先成功获取。不要依赖任何特定的顺序。

话虽如此,当前的内核代码会按照它们阻塞的顺序唤醒它们。这条评论在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.
 */

如果您想让一组进程按顺序运行,请不要使用flock(). 使用 SysV 信号量 ( semget()/ semop())。

为第一个进程之后的每个进程创建一个包含一个信号量的信号量集,并将它们全部初始化为 -1。对于第一个进程之后的每个进程,semop()对该进程的信号量执行一个sem_op值为 0 的操作 - 这将阻止它。第一个进程完成后,它应该semop()对第二个进程的信号量执行一个sem_op值为 1 的操作——这将唤醒第二个进程。在第二个进程完成后,它应该semop()对第三个进程的信号量执行一个sem_op值为 1 的信号量,以此类推。

于 2010-04-14T09:36:30.020 回答