Che*_*eng 5 php multithreading
通过引用flock():删除没有竞争条件的锁定文件?当进程意外死亡时,将flock'ed文件解锁?,
我生成以下代码.我的目的是在任何给定的时间内只允许单线程/单个进程运行临界区代码.
<?php
// Exclusive locking based on function parameters.
$lockFileName = '/tmp/cheok.lock';
// Create if doesn't exist.
$lockFile = fopen($lockFileName, "w+");
if (!flock($lockFile, LOCK_EX)) {
throw new \RumtimeException("Fail to perform flock on $lockFileName");
}
echo "start critical section...\n";
sleep(10);
echo "end critical section.\n";
// Warning: unlink(/tmp/cheok.lock): No such file or directory in
unlink($lockFileName);
flock($lockFile, LOCK_UN);
Run Code Online (Sandbox Code Playgroud)
我会一直得到警告
警告:取消链接(/tmp/cheok.lock):没有这样的文件或目录
当第二个等待进程继续执行时,第一个进程已经删除了物理磁盘文件.第二个进程尝试unlink归档,该进程已被第一个进程删除.
并且,如果第3个进程加入,并尝试执行fopen第2个进程正在尝试执行,该unlink怎么办?
简而言之,执行锁定文件清理的正确方法是什么?
这个问题被标记为multithreading,所以我将在使用 pthreads 的多线程上下文中回答这个问题。
首先,了解一下文件锁定。PHP 手册未能完全解释什么是咨询锁。
取自手册页flock
chunk() 仅放置咨询锁;给定文件的适当权限,进程可以自由地忽略flock()的使用并在文件上执行I/O。
在一个充满了对权限不太了解并使用 cron 作业执行长时间运行的脚本的人的生态系统中,这可能会造成很多痛苦......尽管没有人真正知道这一点。
在多线程(使用 pthreads)的上下文中,您希望远离文件锁定,pthreads 提供了一个更优越的 API 来实现互斥。
下面是创建多个线程并实现互斥的示例代码:
<?php
class Test extends Thread {
public function __construct(Threaded $monitor) {
$this->monitor = $monitor;
}
public function run () {
$this->monitor->synchronized(function(){
for ($i = 0; $i < 1000; $i++)
printf("%s #%lu: %d\n",
__CLASS__, $this->getThreadId(), $i);
});
}
private $monitor;
}
$threads = [];
$monitor = new Threaded();
for ($i = 0; $i < 8; $i++) {
$threads[$i] = new Test($monitor);
$threads[$i]->start();
}
foreach ($threads as $thread)
$thread->join();
Run Code Online (Sandbox Code Playgroud)
由于所有线程共享相同的$monitor,因此您可以使用对象内置的同步Threaded来实现可靠的互斥,从而导致输出类似于:
Test #140561163798272: 0
<-- snip for brevity -->
Test #140561163798272: 999
Test #140561151424256: 0
<-- snip for brevity -->
Test #140561151424256: 999
Test #140561138841344: 0
<-- snip for brevity -->
Test #140561138841344: 999
Test #140561059149568: 0
<-- snip for brevity -->
Test #140561059149568: 999
Test #140561050756864: 0
<-- snip for brevity -->
Test #140561050756864: 999
Test #140561042364160: 0
<-- snip for brevity -->
Test #140561042364160: 999
Test #140561033971456: 0
<-- snip for brevity -->
Test #140561033971456: 999
Test #140561025578752: 0
<-- snip for brevity -->
Test #140561025578752: 999
Run Code Online (Sandbox Code Playgroud)
我们可以看到,每个都相互排除执行传递给Thread中的代码。ClosureThreaded::synchronized