大伙估計在多任務(wù)程序中使用printf打印一些信息是非常歡樂的一件事,運(yùn)氣不錯的話偶爾錯幾個數(shù)據(jù)、亂幾個碼也不是什么大問題,倒霉點(diǎn)的可能就直接掛機(jī)、卡死了,那這些到底是什么原因?qū)е碌哪兀? 今天的這篇文章應(yīng)該可以幫助你解決一大部分問題。
01
兩個概念
1、可重入函數(shù) 多任務(wù)系統(tǒng)中每個進(jìn)程或線程都是由多種執(zhí)行流并發(fā)運(yùn)行的,當(dāng)執(zhí)行流同時進(jìn)入同一個函數(shù)(大部分是由于中斷),而不會導(dǎo)致函數(shù)結(jié)果不確定或者錯誤,就可認(rèn)為該函數(shù)是可重入的。
上圖中的signal一般都是因為中斷等原因產(chǎn)生的,在我們多任務(wù)系統(tǒng)中中斷更是無時無刻的在隨機(jī)發(fā)生著,一旦線程或者進(jìn)程被中斷轉(zhuǎn)而去執(zhí)行消息處理,而恰巧的是此時線程所執(zhí)行的操作與信號處理相同,比如malloc,他們都共享同一個資源(全局堆空間)。 當(dāng)信號處理返回到原來的執(zhí)行流中卻由于信號處理的改寫而受影響,比如重入的問題導(dǎo)致malloc會分配相同的內(nèi)存區(qū)域,或者其他的數(shù)據(jù)篡改,鎖死等,這樣該函數(shù)就是不可重入的。 2、線程安全 多個線程并發(fā)運(yùn)行且執(zhí)行相同的代碼,而不會導(dǎo)致運(yùn)行結(jié)果受影響,我們就認(rèn)為是線程安全。
對于線程安全往往加個互斥鎖就可以解決戰(zhàn)斗,當(dāng)然你如果沒有使用全局變量、靜態(tài)變量等等共享資源,那他們基本上是線程安全的。 其實(shí)從表面上看這兩個概念并沒有太大的差異,無非就是運(yùn)行同一塊代碼,會不會導(dǎo)致不確定的結(jié)果。 3、VS 再仔細(xì)想想,其實(shí)這兩個概念所關(guān)注的層面是不同的,可重入函數(shù)要求相同執(zhí)行流執(zhí)行不會受影響,而線程安全僅僅只是在線程這個層面上進(jìn)行的要求。 所以可重入的要求比線程安全要更加嚴(yán)苛,可重入必定線程安全,而線程安全并不一定可重入,如下圖是他們的關(guān)系:
02
不可重入死鎖
下面我們來簡單分析一下不可重入死鎖的問題 :
上圖我們?yōu)楹瘮?shù)加了互斥lock(不考慮遞歸鎖),那么它就是線程安全的,然而剛把共享資源部分上鎖,隨機(jī)的中斷信號處理發(fā)生了,轉(zhuǎn)而執(zhí)行信號處理函數(shù),而在信號處理中也同樣執(zhí)行相同的Fuction代碼,此時資源已經(jīng)鎖住,必須等待前面調(diào)用Fuction函數(shù)的線程釋放,但此線程又在等待信號處理訪問,最終死鎖,涼涼! 當(dāng)然你可以使用遞歸鎖來進(jìn)行處理,這在正常設(shè)計中是需要避免的,當(dāng)時對于一些需要調(diào)用外部庫的設(shè)計,只能選擇遞歸鎖等。
03
可重入的識別
說實(shí)在對于很多玩RTOS的伙計,直接關(guān)中斷、開中斷的臨界資源保護(hù)就基本告別了一部分不可重入問題,而這樣的操作會影響多任務(wù)的并發(fā)執(zhí)行,但是如果你只是加了幾把鎖,可能在程序中不重入的問題還是要注意一下。 這里不可重入問題不完全總結(jié)了幾點(diǎn):
1、標(biāo)準(zhǔn)IO函數(shù)都會使用到全局的數(shù)據(jù)結(jié)構(gòu),比如printf函數(shù) : 由于使用了全局標(biāo)準(zhǔn)輸出stdout,所以線程不安全也就更不能重入了。
2、malloc和free : 這兩個函數(shù)都是在全局的堆空間上進(jìn)行操作,如果有加鎖那就是線程安全的,但是不可重入。
3、對于全局、靜態(tài)的資源的訪問都會導(dǎo)致線程不安全,比如一些函數(shù)使用的是靜態(tài)緩存區(qū)等,你可以使用本地copy加臨界區(qū)來進(jìn)行保護(hù),盡量使用局部變量。
4、調(diào)用不可重入或者線程不安全的函數(shù)也會繼承對應(yīng)特點(diǎn)。
責(zé)任編輯:xj
原文標(biāo)題:同事"可重入"與"線程安全"老分不清,導(dǎo)致一堆bug!
文章出處:【微信公眾號:嵌入式ARM】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
-
函數(shù)
+關(guān)注
關(guān)注
3文章
4346瀏覽量
62979 -
BUG
+關(guān)注
關(guān)注
0文章
155瀏覽量
15725 -
線程安全
+關(guān)注
關(guān)注
0文章
13瀏覽量
2477
原文標(biāo)題:同事"可重入"與"線程安全"老分不清,導(dǎo)致一堆bug!
文章出處:【微信號:gh_c472c2199c88,微信公眾號:嵌入式微處理器】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論