Posted on 2010-03-12 14:33
rikisand 閱讀(250)
評(píng)論(0) 編輯 收藏 引用
首先,可重入和線程安全是兩個(gè)并不等同的概念,一個(gè)函數(shù)可以是可重入的,也可以是線程安全的,可以兩者均滿足,可以兩者皆不滿組(該描述嚴(yán)格的說(shuō)存在漏洞,參見(jiàn)第二條)。
其次,從集合和邏輯的角度看,可重入是線程安全的子集,可重入是線程安全的充分非必要條件。可重入的函數(shù)一定是線程安全的,然過(guò)來(lái)則不成立。
第三,POSIX 中對(duì)可重入和線程安全這兩個(gè)概念的定義:
Reentrant Function:
A function whose effect, when called by two or more threads,is guaranteed to be as if the threads each executed thefunction one after another in an undefined order, even ifthe actual execution is interleaved.
From IEEE Std 1003.1-2001 (POSIX 1003.1)
-- Base Definitions, Issue 6
Thread-Safe Function:
A function that may be safely invoked concurrently by multiple threads.
另外還有一個(gè) Async-Signal-Safe的概念
Async-Signal-Safe Function:
A function that may be invoked, without restriction fromsignal-catching functions. No function is async-signal -safe unless explicitly described as such.
以上三者的關(guān)系為:
Reentrant Function 必然是Thread-Safe Function和Async-Signal-Safe Function
可重入與線程安全的區(qū)別體現(xiàn)在能否在signal處理函數(shù)中被調(diào)用的問(wèn)題上,可重入函數(shù)在signal處理函數(shù)中可以被安全調(diào)用,因此同時(shí)也是Async-Signal-Safe Function;而線程安全函數(shù)不保證可以在signal處理函數(shù)中被安全調(diào)用,如果通過(guò)設(shè)置信號(hào)阻塞集合等方法保證一個(gè)非可重入函數(shù)不被信號(hào)中斷,那么它也是Async-Signal-Safe Function。
值得一提的是POSIX 1003.1的System Interface缺省是Thread-Safe的,但不是Async-Signal-Safe的。Async-Signal-Safe的需要明確表示,比如fork ()和signal()。
最后讓我們來(lái)構(gòu)想一個(gè)線程安全但不可重入的函數(shù):
假設(shè)函數(shù)func()在執(zhí)行過(guò)程中需要訪問(wèn)某個(gè)共享資源,因此為了實(shí)現(xiàn)線程安全,在使用該資源前加鎖,在不需要資源解鎖。
假設(shè)該函數(shù)在某次執(zhí)行過(guò)程中,在已經(jīng)獲得資源鎖之后,有異步信號(hào)發(fā)生,程序的執(zhí)行流轉(zhuǎn)交給對(duì)應(yīng)的信號(hào)處理函數(shù);再假設(shè)在該信號(hào)處理函數(shù)中也需要調(diào)用函數(shù)func(),那么func()在這次執(zhí)行中仍會(huì)在訪問(wèn)共享資源前試圖獲得資源鎖,然而我們知道前一個(gè)func()實(shí)例已然獲得該鎖,因此信號(hào)處理函數(shù)阻塞——另一方面,信號(hào)處理函數(shù)結(jié)束前被信號(hào)中斷的線程是無(wú)法恢復(fù)執(zhí)行的,當(dāng)然也沒(méi)有釋放資源的機(jī)會(huì),這樣就出現(xiàn)了線程和信號(hào)處理函數(shù)之間的死鎖局面。
因此,func()盡管通過(guò)加鎖的方式能保證線程安全,但是由于函數(shù)體對(duì)共享資源的訪問(wèn),因此是非可重入。