執行緒安全與可重入函式

2021-08-02 15:59:53 字數 1931 閱讀 5286

基本定義

執行緒安全:簡單來說執行緒安全就是多個執行緒併發同一段**時,不會出現不同的結果,我們就可以說該執行緒是安全的;

執行緒不安全:說完了執行緒安全,執行緒不安全的問題就很好解釋,如果多執行緒併發執行時會產生不同的結果,則該執行緒就是不安全的。

執行緒安全產生的原因:大多是因為對全域性變數和靜態變數的操作

常見的執行緒

不安全的函式

(1)不保護共享變數的函式

(2)函式狀態隨著被呼叫,狀態發生變化的函式

(3)返回指向靜態變數指標的函式

(4)呼叫執行緒不安全函式的函式

常見的執行緒

安全的情況

(1)每個執行緒對全域性變數或者靜態變數只有讀取的許可權,而沒有寫入的許可權,一般來說這些執行緒是安全的;

(2)類或者介面對於執行緒來說都是原子操作;

(3)多個執行緒之間的切換不會導致該介面的執行結果存在二義性;

執行**:

#include#includeint value=0;

void* func(void* arg)

}int main()

基本定義

重入:同乙個函式被不同的執行流呼叫,當前乙個流程還沒有執行完,就有其他的程序已經再次呼叫(執行流之間的相互巢狀執行);

可重入:多個執行流反覆執行乙個**,其結果不會發生改變,通常訪問的都是各自的私有棧資源;

不可重入:多個執行流反覆執行一段**時,其結果會發生改變;

可重入函式:當乙個執行流因為異常或者被核心切換而中斷正在執行的函式而轉為另外乙個執行流時,當後者的執行流對同乙個函式的操作並不影響前乙個執行流恢復後執行函式產生的結果;

不可重入函式:當程式執行到某乙個函式的時候,可能因為硬體中斷或者異常而使得在使用者正在執行的**暫時終端轉而進入你核心,這個時候如有乙個訊號需要被處理,而處理的這個訊號的時候又會重新呼叫剛才中斷的函式,如果函式內部有乙個全域性變數需要被操作,那麼,當訊號處理完成之後重新返回使用者態恢復中斷函式的上下文再次繼續執行的時候,對同乙個全域性變數的操作結果可能就會發生改變而並不如我們預期的那樣,這樣的函式被稱為不可重入函式。例如在進行鍊錶的插入時,插入函式訪問乙個全域性鍊錶,有可能因為重入而造成錯亂。

可重入函式

滿足條件

(1)不使用全域性變數或靜態變數;

(2)不使用用malloc或者new開闢出的空間;

(3)不呼叫不可重入函式;

(4)不返回靜態或全域性資料,所有資料都有函式的呼叫者提供;

(5)使用本地資料,或者通過製作全域性資料的本地拷貝來保護全域性資料;

不可重入函式符合以下條件之一

(1)呼叫了malloc/free函式,因為malloc函式是用全域性鍊錶來管理堆的。

(2)呼叫了標準i/o庫函式,標準i/o庫的很多實現都以不可重入的方式使用全域性

資料結構。

(3)可重入體內使用了靜態的資料結構。

可重入函式

分類 (1) 顯式可重入函式

如果所有函式的引數都是傳值傳遞的(沒有指標),並且所有的資料引用都是本地的自動棧變數(也就是說沒有引用靜態或全域性變數),那麼函式就是顯示可重入的,也就是說不管如何呼叫,我們都可斷言它是可重入的。

(2) 隱式可重入函式

可重入函式中的一些引數是引用傳遞(使用了指標),也就是說,在呼叫執行緒小心地傳遞指向非共享資料的指標時,它才是可重入的。

可重入函式可以有多餘乙個任務併發使用,而不必擔心資料錯誤,相反,不可重入函式不能由超過乙個任務所共享,除非能確保函式的互斥(或者使用訊號量,或者在 **的關鍵部分禁用中斷)。可重入函式可以在任意時刻被中斷,稍後再繼續執行,不會丟失資料,可重入函式要麼使用本地變數,要麼在使用全域性變數時保護自己 的資料。

執行**:

#include#includeint value=0;

void fun()

}int main()

執行緒安全與可重入函式

可重入函式 reentrant function 與執行緒安全函式 thread safe function 有時容易混淆,而且各種文件中的解釋也不是很清楚,這裡根據筆者的經驗來說明一下。執行緒安全函式 概念 執行緒安全的概念比較直觀。一般說來,乙個函式被稱為執行緒安全的,當且僅當被多個併發執行緒反...

可重入函式與執行緒安全

執行緒安全 乙個函式被稱為執行緒安全的 thread safe 當且僅當被多個併發程序反覆呼叫時,它會一直產生正確的結果。如果乙個函式不是執行緒安全的,我們就說它是執行緒不安全的 thread unsafe 我們定義四類 有相交的 執行緒不安全函式。將這類執行緒不安全函式變為執行緒安全的,相對比較容...

可重入函式與執行緒安全

可重入函式與執行緒安全 執行緒安全 假如在乙個函式中它是這麼寫的,在乙個全域性鍊錶上存放資料,在單執行緒模式下,我們先new乙個新的節點然後讓head next指向這個節點,這種場景在多執行緒場景下會是這樣的過程,執行緒一new了乙個節點,然後cpu轉去執行執行緒二,執行緒二new乙個節點後head...