執行緒安全和不可重入

藍旭晨楓發表於2016-04-07
執行緒安全問題都是由全域性變數和靜態變數引起的

可重入函式是執行緒安全函式的子集

可重入的要求:不使用、不返回任何非常量的全域性或者靜態變數,也不呼叫任何不可重入函式。它可以被中斷,意味著它除了使用自己棧上的變數不依賴於任何環境(包括static),這樣的函式就是purecode(純程式碼)可重入。可以允許有多個函式的副本在同時執行,因為它們使用的是分離的棧,不會互相干擾。但是對於不可重入的函式,由於使用了一些系統資源比如全域性變數,中斷向量表等,如果它被中斷的話,可能會出現問題,這類函式是不能執行在多工環境下的。

執行緒安全的要求是:在多個執行緒中同時呼叫一個函式時,能夠得到預期的結果,多個執行緒的切換不會導致該介面的執行結果產生二義性。執行緒安全函式在執行時多個執行緒可以互相影響,即使輸入一樣輸出也可能因為中途的其他執行緒的行為而不一樣。所以函式的返回值不具有可再現性。所以也就不一定是可重入函式。

1、如果一個函式的實現使用了全域性或者靜態變數,那麼這個函式既不是可重入的也不是執行緒安全的。
2、但是針對1中的情況,如果放寬條件,這個函式仍然用到了全域性或者靜態變數,但是在訪問這些變數的時候,通過加鎖來保證互斥訪問,那麼這個函式就可以變成執行緒安全的函式。但他此時仍然是不可重入的,因為通常加鎖是針對不同執行緒的訪問,對同一執行緒可能出現問題。
3、所以如果把函式中的全域性或者靜態變數都去掉,並保證在該函式中不會呼叫不可重入函式,那麼這個函式就可以做到既是執行緒安全的,也是可重入的。

所以:可重入函式一般都是執行緒安全的,執行緒安全的不一定是可重入的。可重入函式要求更高,執行緒安全可以用鎖,可重入不行(否則死鎖)

相關文章