線程安全與可重入函數

    在以前的博文中有說過線程,線程是一個執行流,一個指令序列,一個指令分支,爲了共享資源而產生的線程,但只要是資源,都會出現資源的數目與操做安全問題,因此在線程這一塊,設計了信號量,條件變量,各類鎖,來保證資源的訪問獨佔性與原子性。安全

    什麼是線程安全?
數據結構

      線程安全指的是在多線程訪問狀況下,保證線程對臨界資源的操做原子性,在臨界區中,不容許其餘的線程進行插入訪問形成了數據的亂序佔用而修改,產生邏輯結果不一致的問題。
多線程

      線程不安全就是不提供數據訪問保護,出現多個線程前後更改數據形成髒數據。ide

    其實對於線程安全簡單來講,就是保證在多線程狀況下,咱們進行的操做,不管是否控制臨界區的插入訪問,只要保證數據邏輯結果的原子性就是線程安全的,但若出現數據的亂序操做或者中斷操做,達不到預期的結果則就是線程不安全的。
函數


    那麼對於線程安全來講,咱們經過各類控制臨界區的執行權限來進行限制,能夠閱讀以前的博文來進行線程的同步與互斥,線程自己就是爲了共享資源而產生,利用同步與互斥來進行任務邏輯上的運行,既保證協同,有保證邏輯獨有。spa

    

    線程就是一個執行流,一個指令序列,一個指令分支,也就是一個函數。那麼對於函數而言,存在着不須要進行互斥控制的狀況,也就是在多線程狀況下,不管線程之間是如何運行插入修改,都可以保證數據的正確性,就是可重入函數。信號捕捉也是進行函數的操做,因此信號跟線程在原理上是類似的。線程

   

先舉一個不可重入函數的例子:設計

 wKiom1cvIIyR3Fj9AACYMWS253c132.png

針對這張圖片,咱們來分析一下他的過程。blog

  1. 在insert函數中,咱們很明顯的知道,他是一個頭插的函數,
    圖片

  2. 而後在insert函數執行之中,假若在p->next = head以後,head = p以前產生了一個信號捕捉,或者同時運行多個線程,在多個線程之中,線程中斷插入在這之間,就會出現圖片上的結果。

  3. 也就是咱們要達到的目的是咱們要插入2個數據,可是卻只插入了一個數據,另一個數據出現了空間浪費,目的不達到,併產生了髒數據。

    insert函數被不一樣的控制流程調用,有可能在第一次調用還沒返回時就再次進入該函數,這稱爲重入,insert函數訪問一個全局鏈表,有可能由於重入而形成錯亂,像這樣的函數稱爲不可重入函數,反之,若是一個函數只訪問本身的局部變量或參數,則稱爲可重入(Reentrant) 函數。

    

爲何兩個不一樣的控制流程調用同一個函數,訪問它的同一個局部變量或參數就不會形成錯亂?

    在線程之中,線程雖然強調資源共享,可是他們的棧倒是獨有的,因此訪問它的同一個局部變量或參數就不會形成錯亂。


不可重入函數的條件:

調用了malloc或free,由於malloc也是用全局鏈表來管理堆的。

調用了標準I/O庫函數。標準I/O庫的不少實現都以不可重入的方式使用全局數據結構。

SUS規定有些系統函數必須以線程安全的方式實現,這裏就不列了。



總結:

    對於線程安全來講,就是保證在多線程邏輯環境下的數據操做不產生反作用影響,從而出現了各類保證線程安全的操做,條件變量,信號量,各類鎖。

    線程其實是一個指令序列,一個執行流,一個函數。因此對於線程之中,若在多線程環境下不論怎麼中斷插入,都不影響數據邏輯的函數叫作可重入函數。

相關文章
相關標籤/搜索