什麼是線程安全

一、開發版本

在PHP安裝版本中存在兩個版本,線程安全版本和線程非安全版本php

下面是對開發版本的解釋:web

ts(Thread-Safety)即線程安全,多線程訪問時,採用了加鎖機制,當一個線程訪問該類的某個數據時,進行保護,其餘線程不能進行訪問直到該線程讀取完,其餘線程纔可以使用。不會出現數據不一致或者數據污染php以ISAPI方式加載的時候選擇這個版本.,php以ISAPI方式加載的時候選擇這個版本。
nts(None-Thread Safe)即非線程安全,就是不提供數據訪問保護,有可能出現多個線程前後更改數據形成所獲得的是 髒數據php以fast cgi方式運行的時候選擇這個版本,具備更好的性能;

具體在哪裏能夠看呢,以下圖打印phpinfo()會顯示一些配置信息:
1590417033.png數據庫

好在咱們在使用PHP版本的時候,不用能夠去區分線程安全和非線程安全。ISAPI方式加載的時候選擇這,由微 軟提出,故只能在win平臺上運行。在Linux運行的都是線程非安全版本,不論在什麼平臺、用什麼web server,只要是用cgi/fastcgi方式運行PHP,都用非線性安全。安全

產生線程不安全的緣由

在單線程的開發過程當中是不會存在線程安全問題的,只有在多線程的使用過程當中,多個線程訪問共享資源的時候,纔會出現線程安全問題。只要資源沒有發生變化,多個線程讀取相同的資源就是安全的。

結合一下超買超賣的應用場景。想象下線程A和B同時執行同一個商品下訂單。多線程

A:讀取商品的庫存爲1
B:讀取商品的庫存爲1
A:下單成功扣減庫存 -1
B:下單成功扣減庫存 -1
B:操做成功,庫存減小爲-1

此時會發現,庫存只有一件的商品,被賣出去了兩次。出現了超賣的現象。結合線程產生不安全的緣由分析:只要資源沒有發生變化,線程就是安全的,如今訪問的資源的庫存發生了變化,致使線程變爲了避免安全。併發

常見的高併發致使的超賣超買的問題,用更專業的術語來講的話就是線程不安全。
那麼問題來了,怎麼使線程變爲安全呢?本文從代碼層面來分析(其餘層面分析請閱讀小編其餘文章)能夠從資源不被多個線程共享和順序執行(加鎖)兩個角度入手分析

局部變量

局部變量存儲在線程本身的棧中。也就是說,局部變量永遠也不會被多個線程共享。因此,基礎類型的局部變量是線程安全的。下面是基礎類型的局部變量的一個例子:高併發

public void someMethod(){
   $value = 0;
   $value++;
}

判斷資源對象是不是線程安全

若是一個資源的建立,使用,銷燬都在同一個線程內完成,且永遠不會脫離該線程的控制,則該資源的使用就是線程安全的。

引用不是線程安全的!

重要的是要記住,即便一個對象是線程安全的不可變對象,指向這個對象的引用也可能不是線程安全的性能

class Calculator{
    private $currentValue = null;

    public function getValue(){
        return $this.currentValue;
    }
    //傳入的參數的引用的變量,將引用變量賦值給currentValue,隨着引用變量的改變,currentValue的也會跟着改變
    public function setValue(&$newValue){
        $this.currentValue = $newValue;
    }
}

最後

那麼問題來了,在上面超買超賣,使用了線程安全的寫法實現後就不存在線程安全了嗎?結果是即使是程序代碼的實現了線程安全,商品的庫存是存在在數據庫的,兩個安全的線程,讀取數據庫庫存進行修改,也會有存在競爭關係。這個時候就用採用加鎖的方式來實現了,參考小編其餘文章。this

相關文章
相關標籤/搜索