可重入函數與線程安全關係

什麼是可重入函數和不可重入函數

可重入函數


     在 實時系統的設計中,經常會出現多個任務調用同一個函數的情況。如果這個函數不幸被設計成爲不可重入的函數的話,那麼不同任務調用這個函數時可能修改其他任 務調用這個函數的數據,從而導致不可預料的後果。那麼什麼是可重入函數呢?所謂可重入是指一個可以被多個任務調用的過程,任務在調用時不必擔心數據是否會 出錯。不可重入函數在實時系統設計中被視爲不安全函數。


     滿足下列條件的函數多數是不可重入的:

 


(1)函數體內使用了靜態的數據結構;


(2)函數體內調用了malloc()或者free()函數;


(3)函數體內調用了標準I/O函數。



線程安全:概念比較直觀。一般說來,一個函數被稱爲線程安全的,當且僅當被多個併發線程反覆調用時,它  會一直產生正確的結果。

 
可重入:概念基本沒有比較正式的完整解釋,但是它比線程安全要求更嚴格。根據經驗,所謂“重入”,常見的情況是,程序執行到某個函數foo()時,收到信號,於是暫停目前正在執行的函數,轉到信號處理函數,而這個信號處理函數的執行過程中,又恰恰也會進入到剛剛執行的函數foo(),這樣便發生了所謂的重入。此時如果foo()能夠正確的運行,而且處理完成後,之前暫停的foo()也能夠正確運行,則說明它是可重入的。


線程安全的條件:


要確保函數線程安全,主要需要考慮的是線程之間的共享變量。屬於同一進程的不同線程會共享進程內存空間中的全局區和堆,而私有的線程空間則主要包括棧和寄存器。因此,對於同一進程的不同線程來說,每個線程的局部變量都是私有的,而全局變量、局部靜態變量、分配於堆的變量都是共享的。在對這些共享變量進行訪問時,如果要保證線程安全,則必須通過加鎖的方式。


可重入的判斷條件:

 

要確保函數可重入,需滿足一下幾個條件:

1、不在函數內部使用靜態或全局數據 
2、不返回靜態或全局數據,所有數據都由函數的調用者提供。 
3、使用本地數據,或者通過製作全局數據的本地拷貝來保護全局數據。
4、不調用不可重入函數。

 

 

可重入與線程安全並不等同,一般說來,可重入的函數一定是線程安全的,但反過來不一定成立。

 

如果我們的線程函數不是線程安全的,那在多線程調用的情況下,可能導致的後果是顯而易見的——共享變量的值由於不同線程的訪問,可能發生不可預料的變化,進而導致程序的錯誤,甚至崩潰。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章