1、可重入函數html
可重入函數主要用於多任務環境中,一個可重入的函數簡單來講就是能夠被中斷的函數,也就是說,能夠在這個函數執行的任什麼時候刻中斷它,轉入OS調度下去執行另一段代碼,而返回控制時不會出現什麼錯誤;,局部變量可重入函數; 不可重入的函數因爲使用了一些系統資源,好比全局變量區,中斷向量表等,因此它若是被中斷的話,可能會出現問題,這類函數是不能運行在多任務環境下的。node
main函數調用insert函數向一個鏈表head中插入節點node1,插入操做分爲兩步,剛作完第一步的 時候,由於硬件中斷使進程切換到內核,再次回用戶態以前檢查到有信號待處理,因而切換到sighandler函數,sighandler也調用insert函數向同一個鏈表head中插入節點node2,插入操做的兩步都作完以後從ighandler返回內核態,再次回到用戶態就從main函數調用的insert函數中繼續往下執行,先前作第一步以後被打斷,如今繼續作完第二步。結果是,main函數和sighandler前後向鏈表中插入兩個節點,而最後只有一個節點真正插入鏈表中了。這就出現了泄漏。像上例這樣,insert函數被不一樣的控制流程調用,有可能在第一次調用還沒返回時就再次進入該函數,這稱爲重入,insert函數訪問一個全局鏈表,有可能由於重入而形成錯亂,像這樣的函數稱爲不可重入函數,反之,若是一個函數只訪問本身的局部變量或參數,則稱爲可重入(Reentrant) 函數數據結構
一、 若是一個函數符合如下條件之一則是不可重入的多線程
①、調用了malloc或free,由於malloc也是用全局鏈表來管理堆的。ide
②、調用了標準I/O庫函數。標準I/O庫的不少實現都以不可重入的方式使用全局數據結構。函數
2、線程安全spa
若是代碼所在的進程中有多個線程在同時運行,而這些線程可能會同時運行這段代碼。若是每次運行結果和單線程運行的結果是同樣的,並且其餘的變量的值也和預期的是同樣的,就是線程安全的。或者說:一個類或者程序所提供的接口對於線程來講是原子操做或者多個線程之間的切換不會致使該接口的執行結果存在二義性, 線程
線程安全問題都是由全局變量及靜態變量引發的。若每一個線程中對全局變量、靜態變量只有讀操做,而無寫操做,通常來講,這個全局變量是線程安全的;如有多個線程同時執行寫操做,通常都須要考慮線程同步,不然的話就可能影響線程安全。產生線程安全的本質在於:線程共享和執行流發生了干擾。要確保線程安全,線程在對共享變量進行訪問時必須以加鎖的方式。orm
好比一個 ArrayList 類,在添加一個元素的時候,它可能會有兩步來完成:1. 在 Items[Size] 的位置存放此元素;2. 增大 Size 的值。
在單線程運行的狀況下,若是 Size = 0,添加一個元素後,此元素在位置 0,並且 Size=1;而若是是在多線程狀況下,好比有兩個線程,線程 A 先將元素存放在位置 0。可是此時 CPU 調度線程A暫停,線程 B 獲得運行的機會。線程B也向此 ArrayList 添加元素,由於此時 Size 仍然等於 0 (注意,咱們假設的是添加一個元素是要兩個步驟哦,而線程A僅僅完成了步驟1),因此線程B也將元素存放在位置0。而後線程A和線程B都繼續運行,都增長 Size 的值。那好,咱們來看看 ArrayList 的狀況,元素實際上只有一個,存放在位置 0,而 Size 卻等於 2。這就是「線程不安全」了。
3、可重入函數與線程安全的聯繫與區別
一、可重入函數必定是線程安全的,單線程安全不必定是可重入的