線程安全函數安全
概念:
線程安全的概念比較直觀。通常說來,一個函數被稱爲線程安全的,當且僅當被多個併發線程反覆調用時,它會一直產生正確的結果。
確保線程安全:
要確保函數線程安全,主要須要考慮的是線程之間的共享變量。屬於同一進程的不一樣線程會共享進程內存空間中的全局區和堆,而私有的線程空間則主要包括棧和寄存器。所以,對於同一進程的不一樣線程來講,每一個線程的局部變量都是私有的,而全局變量、局部靜態變量、分配於堆的變量都是共享的。在對這些共享變量進行訪問時,若是要保證線程安全,則必須經過加鎖的方式。
線程不安全的後果:
線程不安全可能致使的後果是顯而易見的——共享變量的值因爲不一樣線程的訪問,可能發生不可預料的變化,進而致使程序的錯誤,甚至崩潰。 多線程
可重入函數
概念:
在多線程或有異常控制流的狀況下,當某個函數運行到中途時,控制流(也就是當前指令序列)就有可能被打斷而去執行另外一個函數.而"另外一個函數"頗有多是它自己.,若是在這種狀況下不會出現問題,好比說數據或狀態不會被破壞,行爲肯定。那麼這個函數就被稱作"可重入"的.函數是可重入(reentrant)的,是指對於相同的(而且合法的)函數參數(包括無參函數的狀況),屢次重複調用此函數產生的行爲是可預期的,即函數的行爲一致,或者結果相同。不能保證這一點的函數稱爲不可重入(non-reentrant)函數。併發
確保可重入:
要確保函數可重入,需知足如下幾個條件:
一、不在函數內部使用靜態或全局數據
二、不返回靜態或全局數據,全部數據都由函數的調用者提供。
三、使用本地數據,或者經過製做全局數據的本地拷貝來保護全局數據。
四、不調用不可重入函數。
不可重入的後果:
不可重入的後果主要體如今象信號處理函數這樣須要重入的狀況中。若是信號處理函數中使用了不可重入的函數,則可能致使程序的錯誤甚至崩潰。
ide
可重入與線程安全函數
可重入與線程安全並不等同。通常說來,可重入的函數必定是線程安全的,但反過來不必定成立。它們的關係可用下圖來表示:spa
咱們能夠採用下面的變化過程來進一步說明上圖:
- 若是一個函數中用到了全局或靜態變量,那麼它不是線程安全的,也不是可重入的;
- 若是咱們對它加以改進,在訪問全局或靜態變量時使用互斥量或信號量等方式加鎖,則可使它變成線程安全的,但此時它仍然是不可重入的,由於一般加鎖方式是針對不一樣線程的訪問,而對同一線程可能出現問題;
- 若是將函數中的全局或靜態變量去掉,改爲函數參數等其餘形式,則有可能使函數變成既線程安全,又可重入。
好比:strtok函數是既不可重入的,也不是線程安全的;加鎖的strtok不是可重入的,但線程安全;而strtok_r既是可重入的,也是線程安全的。線程