大家都寫過C語言中的函數(shù),但有沒有想過中斷函數(shù)可重入是什么,你編寫的函數(shù)在同一個(gè)時(shí)刻是否允許被多個(gè)調(diào)用者調(diào)用呢?是不是不管誰來調(diào)用,有多少個(gè)調(diào)用者同時(shí)調(diào)用,都能給出一致的表現(xiàn),返回一致的結(jié)果?
一個(gè)函數(shù)在不同的調(diào)用時(shí)刻,會(huì)表現(xiàn)不一致!?這個(gè)比較奇怪,函數(shù)不是已經(jīng)寫好的嗎? 怎么會(huì)表現(xiàn)出不同的行為呢?另外,我怎么可能在一個(gè)程序里面多個(gè)地方同時(shí)調(diào)用同一個(gè)函數(shù)呢?
其一,答案很簡(jiǎn)單。函數(shù)可能使用了能長(zhǎng)期存活的靜態(tài)數(shù)據(jù),俗稱老不死數(shù)據(jù)。為什么我要給他取這個(gè)難聽的名字,因?yàn)殪o態(tài)數(shù)據(jù)不僅會(huì)是的函數(shù)每次調(diào)用彼此耦合牽連(除非你是有意而為之),而且會(huì)在不調(diào)用的時(shí)候占著內(nèi)存不拉shi,而且會(huì)讓并發(fā)任務(wù)極容易產(chǎn)生競(jìng)態(tài),不利于生產(chǎn)!
函數(shù)還可能是一個(gè)使用了別的使用了老不死數(shù)據(jù)的函數(shù)的函數(shù)。(此句充分展現(xiàn)了我是一個(gè)能定義嵌套遞歸概念的合格碼農(nóng)的基本素養(yǎng))
函數(shù)里面的數(shù)據(jù)還可能直接受制于硬件條件。這在嵌入式系統(tǒng)代碼中也是很常見D。
其二,你的程序很可能是一個(gè)多線程并發(fā)的實(shí)例,因此多個(gè)地方同時(shí)調(diào)用同一個(gè)函數(shù)的情況,很普遍。
綜上所述的函數(shù)行為總結(jié)一個(gè)概念就是:在多次調(diào)用中(不管是否同時(shí))行為變現(xiàn)一致的函數(shù),被稱為可重入函數(shù)中斷函數(shù)可重入是什么,否則被稱為不可重入函數(shù)。
POSIX.1-20001標(biāo)準(zhǔn)規(guī)定,所有的標(biāo)準(zhǔn)庫函數(shù)都必須是可重入函數(shù),除了以下這些:
正如其名所提示的,我們?cè)诔绦蛑校瑫r(shí)調(diào)用這些函數(shù)有可能會(huì)產(chǎn)生不一致的結(jié)果,產(chǎn)生這樣結(jié)果的原因有三,上面已經(jīng)提到,用比較官方嚴(yán)肅的語言來表述如下:
一是因?yàn)楹瘮?shù)內(nèi)部使用了共享資源,比如全局變量、環(huán)境變量。
二是因?yàn)楹瘮?shù)內(nèi)部調(diào)用了其他不可重入函數(shù)。
三是因?yàn)楹瘮?shù)執(zhí)行結(jié)果與某硬件設(shè)備相關(guān)。
從這點(diǎn)出發(fā),如果你想要寫一個(gè)線程安全的可重入函數(shù)的話,只要遵循以下原則就行了:
A) 不使用任何靜態(tài)(老不死)數(shù)據(jù),只使用局部變量或者堆內(nèi)存。
B) 不調(diào)用上表中的任何非線程安全的不可重入函數(shù)。
如果不能同時(shí)滿足以上兩個(gè)條件,可以使用信號(hào)量、互斥鎖等機(jī)制來確保使用靜態(tài)數(shù)據(jù)或者調(diào)用不可重入函數(shù)時(shí)的互斥效果。其實(shí),這也是編寫多線程程序必須要注意的地方啦!