若乙個程式或子程式可以「安全的被並行執行(parallel computing)」,則稱其為可重入(reentrant或re-entrant)的。即當該子程式正在執行時,可以再次進入並執行它(並行執行時,個別的執行結果,都符合設計時的預期)。可重入概念是在單執行緒作業系統的時代提出的。乙個子程式的重入,可能由於自身原因,如執行了jmp或者call,類似於子程式的遞迴呼叫;或者由於硬體中斷,unix系統的signal的處理,即子程式被中斷處理程式或者signal處理程式呼叫。重入的子程式,按照後進先出線性序依次執行。
若乙個函式是可重入的,則該函式:
多「使用者/物件/程序優先順序」以及多執行緒,一般會使得對可重入**的控制變得複雜。同時,io**通常不是可重入的,因為他們依賴於像磁碟這樣共享的、單獨的(類似程式設計中的靜態(static)、全域(global))資源。
可重入性是函式程式語言的關鍵特性之一。 例子
在以下的c語言**中,函式f
和函式g
都不是可重入的。
int g_var = 1;以上**中,int f()
int g()
f
使用了全域性變數 g_var,所以,如果兩個執行緒同時執行它並訪問g_var
,則返回的結果取決於執行的時間。因此,f
不可重入。而g
呼叫了f
,所以它也不可重入。
稍作修改後,兩個函式都是可重入的:
int f(int i)可重入與執行緒安全兩個概念都關係到函式處理資源的方式。但是,他們有一定的區別。可重入概念會影響函式的外部介面,而執行緒安全只關心函式的實現。int g(int i)
執行緒安全與可重入性是兩個不同性質的概念。可重入是在單執行緒作業系統背景下,重入的函式或者子程式,按照後進先出的線性序依次執行完畢。多執行緒執行的函式或子程式,各個執行緒的執行時機是由作業系統排程,不可預期的,但是該函式的每個執行執行緒都會不時的獲得cpu的時間片,不斷向前推進執行進度。可重入函式未必是執行緒安全的;執行緒安全函式未必是可重入的。例如,乙個函式開啟某個檔案並讀入資料。這個函式是可重入的,因為它的多個例項同時執行不會造成衝突;但它不是執行緒安全的,因為在它讀入檔案時可能有別的執行緒正在修改該檔案,為了執行緒安全必須對檔案加「同步鎖」。另乙個例子,函式在它的函式體內部訪問共享資源使用了加鎖、解鎖操作,所以它是執行緒安全的,但是卻不可重入。因為若該函式乙個例項執行到已經執行加鎖但未執行解鎖時被停下來,系統又啟動該函式的另外乙個例項,則新的例項在加鎖處將轉入等待。如果該函式是乙個中斷處理服務,在中斷處理時又發生新的中斷將導致資源死鎖。
下述例子,是執行緒安全的,但不是可重入的。
intfunction
()
多執行緒執行時,獲得了互斥鎖的執行緒總能獲得cpu時間片,向前推進執行進度,最終解開互斥鎖,使得別的執行緒也能獲得互斥鎖進入臨界區。但是,如果在單執行緒背景下第一次執行該函式時已經獲得互斥鎖進入臨界區,這時該函式被重入執行,這將在重新申請互斥鎖時被餓死(starvation),因為獲得了互斥鎖的該函式的第一次執行將永遠沒有機會再獲得cpu時間片。
執行緒安全與可重入函式
可重入函式 reentrant function 與執行緒安全函式 thread safe function 有時容易混淆,而且各種文件中的解釋也不是很清楚,這裡根據筆者的經驗來說明一下。執行緒安全函式 概念 執行緒安全的概念比較直觀。一般說來,乙個函式被稱為執行緒安全的,當且僅當被多個併發執行緒反...
可重入函式與執行緒安全
執行緒安全 乙個函式被稱為執行緒安全的 thread safe 當且僅當被多個併發程序反覆呼叫時,它會一直產生正確的結果。如果乙個函式不是執行緒安全的,我們就說它是執行緒不安全的 thread unsafe 我們定義四類 有相交的 執行緒不安全函式。將這類執行緒不安全函式變為執行緒安全的,相對比較容...
可重入函式與執行緒安全
可重入函式與執行緒安全 執行緒安全 假如在乙個函式中它是這麼寫的,在乙個全域性鍊錶上存放資料,在單執行緒模式下,我們先new乙個新的節點然後讓head next指向這個節點,這種場景在多執行緒場景下會是這樣的過程,執行緒一new了乙個節點,然後cpu轉去執行執行緒二,執行緒二new乙個節點後head...