畫江湖之 PHP 多執行緒開發 【執行緒安全 互斥鎖】

Krisji發表於2019-04-05

基本概念

執行緒同步的一種方式,保證共享資料操作的完整性。每個物件都對應於一個可稱為“互斥鎖”的標記,這個標記用來保證在任一時刻,只能有一個執行緒訪問該物件

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");
    }
}

相關文章