執行緒安全與可重入函式

2021-08-02 14:35:02 字數 2238 閱讀 3667

一,什麼是執行緒安全?

所謂的執行緒安全是指在多執行緒中,即使有多個程序訪問同乙份**也不會造成不確定的結果。

即:多個執行緒完成乙個任務與乙個執行緒去完成的結果總是一樣的,並且不會產生預料之外的結果,那麼這樣的執行緒便是安全的。

二,怎麼保證執行緒是安全的?

對於多執行緒的程式訪問衝突的問題十分常見,而最簡單的方法便是引入互斥鎖,通過互斥鎖可以實現拿到鎖的執行緒可以正常執行,而沒有拿到的,只有等待,不能訪問共享資源,直到鎖被釋放。

eg:請看如下**:

#include

#include

#include

int count=0;

void* mypthread1(void)

}int main()

pthead_create()函式是用來建立乙個執行緒的,如上可得我們建立了兩個執行緒分別為p1和p2,然後用這兩個執行緒分別計算從0加到5000的值,很明顯最後答案的輸出count會是10000,那麼實際情況呢?

如下是linux下執行得到的結果

第一次,

第二次:

其實不管試多少次我們都會發現結果很少會是正確,而這便是執行緒安全的問題了,當兩個執行緒不加限制的去訪問val時可能拿到的並不是當前正確的值,例如當a執行緒剛拿到val時,而b執行緒可能正在拿之前val進行計算,因此最後便導致了結果的不確定性。

為了解決問題,我們加入互斥鎖,

如下為改造後的**:

#include

#include

#include

int count=0;

pthread_mutex_t mutex = pthread_mutex_initializer; //申請乙個公共鎖

void* mypthread1(void)

}int main()

如下為改造後的結果:

通過加鎖的方式,現在便可以實現,執行緒每次的操作都會是原子的,所以結果將會一直是10000.

三,什麼是可重入函式?

可重入函式:

在 實時系統的設計中,經常會出現多個任務呼叫同乙個函式的情況。如果這個函式不幸被設計成為不可重入的函式的話,那麼不同任務呼叫這個函式時可能修改其他任 務呼叫這個函式的資料,從而導致不可預料的後果。那麼什麼是可重入函式呢?所謂可重入是指乙個可以被多個任務呼叫的過程,任務在呼叫時不必擔心資料是否會 出錯。不可重入函式在實時系統設計中被視為不安全函式。

滿足下列條件的函式多數是不可重入的:

(1)函式體內使用了靜態的資料結構;

(2)函式體內呼叫了malloc()或者free()函式;

(3)函式體內呼叫了標準i/o函式。

如何寫出可重入的函式?

在函式體內不訪問那些全域性變數,不使用靜態區域性變數,堅持只使用預設態(auto)區域性變數,寫出的函式就將是可重入的。如果必須訪問全域性變數,記住利用互斥訊號量來保護全域性變數。或者呼叫該函式前關中斷,呼叫後再開中斷。

可重入函式可以被乙個以上的任務呼叫,而不必擔心資料被破壞。可重入函式任何時候都可以被中斷,一段時間以後又可以執行,而相應的資料不會丟失。可重入函式或者只使用區域性變數,即儲存在cpu暫存器中或堆疊中;或者使用全域性變數,則要對全域性變數予以保護。

四,執行緒安全與可重入函式的對比

可重入函式與執行緒安全的區別與聯絡:

(1)執行緒安全是在多個執行緒情況下引發的,而可重入函式可以在只有乙個執行緒的情況下。

(2)執行緒安全不一定是可重入的,而可重入函式則一定是執行緒安全的。

(3)如果乙個函式中有全域性變數,那麼這個函式既不是執行緒安全也不是可重入的。

(4)如果將對臨界資源的訪問加上鎖,則這個函式是執行緒安全的,但如果這個重入函式若鎖還未釋放則會產生死鎖,因此是不可重入的。

(5)執行緒安全函式能夠使不同的執行緒訪問同一塊位址空間,而可重入函式要求不同的執行流對資料的操作互不影響使結果是相同的。

執行緒安全與可重入函式

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

可重入函式與執行緒安全

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

可重入函式與執行緒安全

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