PHP pthreads v3下同步处理synchronized用法示例(2)
结果如下图所示:

我们通过notify()和wait()控制了两个for循环,来回的输出变量i的值,保证了顺序性。
我们再来看一个复杂点的例子,共享的资源,如果不进行同步操作,会出现不可预知的情况,代码如下:
<?php
class Task extends Thread
{
private $name;
private $file;
public function __construct($name, $file)
{
$this->name = $name;
$this->file = $file;
}
public function run()
{
$data = file_get_contents($this->file);
$data = floatval($data);
for ($i = 0; $i < 100000; $i++) {
++$data;
}
file_put_contents($this->file, $data);
echo "task : {$this->name} data : {$data} \n";
}
}
$tasks = [];
$file = './test.log';
for ($i = 0; $i < 100; $i++) {
$tasks[$i] = new Task($i, $file);
$tasks[$i]->start();
}
for ($i = 0; $i < 100; $i++) {
$tasks[$i]->join();
}
我们开100个线程对文件test.log进行读写,理想状态下,test.log中的数据应该是每次增加10000000的。现在的电脑配置都比较好,大家可以多运行几次就可以看出效果。

很明显最后的数据好像少了200000,多线程下对test.log文件进行读写,而我们又没有加锁,显然是会出现数据混乱的。
现在我们修改一下代码,如下:
<?php
class File extends Thread
{
private $file;
public function __construct($file)
{
$this->file = $file;
}
public function inc()
{
//进行同步控制,当100个task线程调用inc方法时,synchronized可以保证块内的代码是同步的
//注意,注意,不要把inc方法写到Task里,那样是没效果的,因为每个task线程都是独立空间,他们各自调各自的inc方法,是没法做到同步的
//常用的做法是我们要同步哪些资源,就为这些资源写个Thread类,并提供操作这些资源的方法,并在方法里加上synchronized
return $this->synchronized(function () {
$data = file_get_contents($this->file);
$data = floatval($data);
for ($i = 0; $i < 100000; $i++) {
++$data;
}
file_put_contents($this->file, $data);
return $data;
});
}
}
class Task extends Thread
{
private $name;
private $file;
public function __construct($name, $file)
{
$this->name = $name;
$this->file = $file;
}
public function run()
{
$data = $this->file->inc();
echo "task : {$this->name} data : {$data} \n";
}
}
$tasks = [];
$file = new File('./test.log');
for ($i = 0; $i < 100; $i++) {
$tasks[$i] = new Task($i, $file);
$tasks[$i]->start();
}
for ($i = 0; $i < 100; $i++) {
$tasks[$i]->join();
}
内容版权声明:除非注明,否则皆为本站原创文章。
