線程安全這個詞對我來說已經不是很陌生的了,但是遇到一個叫做可重入函數的詞,它給我的感覺和線程安全是這麼的相近,但既然拿出來了,肯定是有區別的,下面就說說他們之間的區別和聯系。
要先解釋這兩個詞語才行。
線程安全:似乎是在牛客網刷題的時候看到一個正確的選項說的是,線程安全問題都是由全局變量及靜態變量引起的。
可重入函數:按我現在的理解就是,因為不同的執行流執行同一個函數,導致函數的執行順序和預期的函數執行順序不同導致執行邏輯不正確,得不到正確的結果
這麼一看,可重入函數和線程安全似乎沒有什麼大的關系,下面給出兩個比較典型的例子,來看一下。
線程安全:先說一下環境,如下面的代碼表示的一樣,a和b都是靜態變量(也就是說是全局可見的),兩段代碼都在同一個項目中
1 static int a; 2 static int b; 3 a=10;
//!!!!!!!! 4 b=a;
a=5;
//!!!!!! a=b;
看著兩段代碼似乎沒什麼關系,各自執行各自的,但是當有兩個線程(都屬於同一個進程)同時跑這個程序的時候,問題就出現了,也就是線程A和線程B的執行順序:
線程A:a=10;
線程B:a=5;
線程A:b=a;
線程B:a=b;
本來b是要等於10的,但由於線程B先執行了a=5導致b最終結果編程5出現了錯誤。這就是一個簡單的線程安全的例子。
可重入函數:常見的情況是,程序執行到某個函數foo()時,收到信號,於是暫停目前正在執行的函數,轉到信號處理 函數,而這個信號處理函數的執行過程中,又恰恰也會進入到剛剛執行的函數foo(),這樣便發生了所謂的重入,那麼這麼做的結果會變成什麼樣子呢?
當執行完第一次insert的時候,假設此時發生了中斷,導致系統陷入內核,當系統准備從內核態切換到用戶態的時候檢查到此時有信號待處理,於是調用信號處理函數(就是注冊好的signalhandler啦),但是恰好注冊的函數中有一次對insert進行了調用,這就相當於有兩個人同時進入了一個小黑屋裡一樣,有多個執行流在對該函數進行操作,最終導致內存洩漏,丟失了對node2的控制。
這樣看來,線程安全和可重入的問題都是因為執行流的問題引起的了。
很顯然,如果一個函數是可重入函數,那麼它一定是線程安全的,但是如果一個函數是線程安全的,它不一定是可重入函數,就跟上圖中舉得例子一樣的,很明顯insert函數是線程安全的,但是它並不是可重入函數
那麼究竟什麼是可重入函數的定義呢?
在多線程或有異常控制流的情況下,當某個函數運行到中途時,控制流(也就是當前指令序列)就有可能被打斷而去執行另一個函數.而"另一個函數"很有可能是它本身.,如果在這種情況下不會出現問題,比如說數據或狀態不會被破壞,行為確定。那麼這個函數就被稱做"可重入"的.
可重入函數需要滿足什麼條件呢?
http://xxxxxx/Linuxjc/1141596.html TechArticle