画江湖之 PHP 多线程开发 [线程安全 互斥锁]
基本概念
线程同步的一种方式,保证共享数据操作的完整性。每个对象都对应于一个可称为“互斥锁”的标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象
同步控制方法 使用的函数
Threaded::synchronized() 在发起调用的线程上下文中获取对象同步锁,
然后同步执行代码块
Threaded::wait() 让发起调用的线程上下文进入等待,
直到收到其它线程的唤醒通知(notify)
Threaded::notify() 给对象发送唤醒通知
代码段
<?php
// 继承 Thread 的类具有创建线程的能力
class Request extends Thread
{
private $file;
public function __construct($file)
{
$this->file = $file;
}
public function run()
{
//发起一个上下文 获取同步锁
$this->synchronized(function ($thread) {
if (! $thread->done) {
$thread->wait();//一个阻塞等待
}
//执行业务逻辑
$c = file_get_contents($this->file);
echo "before c = {$c}\n";
$c = $c + 1;
echo "after c = {$c}\n";
file_put_contents($this->file, $c);
}, $this);
}
}
$file = '/tmp/data.txt';
$arr = [];
for ($i = 0; $i < 2000; $i++) {//2000个并发访问
$request = new Request($file);
$arr[$i] = $request;
// 创建新线程,随后线程会执行 run 方法
if (! $request->start()) {
die("Start thread failed\n");
}
//创建好一个线程
$request->synchronized(function ($thread) {
$thread->done = true;
$thread->notify();//唤醒通知 然后让别的线程获取到锁
}, $request);
}
for ($i = 0; $i < 2000; $i++) {
// join 是阻塞的,所以脚本运行时间取决于耗时最长的线程
if (! $arr[$i]->join()) {
die("Join failed\n");
}
}
本作品采用《CC 协议》,转载必须注明作者和本文链接