多執行緒 執行緒安全

2021-10-25 10:57:18 字數 3287 閱讀 5537

執行緒安全:多個執行流對臨界資源的爭搶訪問,但是不會出現資料二義性;

執行緒安全的實現:

同步:通過條件判斷保證對臨界資源訪問的合理性

互斥:通過同一時間對臨界資源訪問的唯一性實現臨界資源訪問的安全性

互斥鎖實現的原理:互斥鎖本身是乙個只有0/1的計數器,描述了乙個臨界資源當前的訪問狀態,所有執行流在訪問臨界資源,都需要先判斷當前的臨界資源狀態是否允許訪問,如果不允許則讓執行流等待,否則可以讓執行流訪問臨界資源,但是在訪問期間需要將狀態修改為不可訪問狀態,這期間如果有其他執行流想要訪問,則不被允許。

互斥鎖具體的操作流程以及介面介紹:

定義互斥鎖變數pthread_mutex_t mutex;

pthread_mutex_init(pthread_mutex_t mutex,pthread_mutexattr_t attr);

pthread_mutex_t mutex=pthread_mutex_initializer;定義並且初始化

在訪問臨界資源之前進行加鎖操作(不能加鎖則等待,可以加鎖則修改資源狀態,然後呼叫返回,訪問臨界資源)

pthread_mutex_lock(pthread_mutex_t mutex);

pthread_mutex_trylock(pthread_mutex_t *mutex);(非阻塞:不能加鎖立即報錯返回)

掛起等待:將執行緒狀態置為可中斷休眠狀態–表示當前休眠;

被喚醒:將執行緒狀態置為執行狀態

在臨界資源訪問完畢之後進行解鎖操作(將資源狀態置為可訪問,將其他執行流喚醒)

pthread_mutex_unlock(pthread_mutex_t mutex);

銷毀互斥鎖

pthread_mutex_destroy(pthread_mutex_t mutex)

所有的執行流都需要通過同乙個互斥鎖實現互斥,意味著互斥鎖本身就是乙個臨界資源,大家都會訪問

如果互斥鎖本身的操作都不安全如何保證別人安全,所以互斥鎖本身的操作首先必須是安全的------互斥鎖自身計數的操作是原子操作

我們可以發現互斥鎖,我們實現**中有四個執行緒,但是模擬搶票的時候,只有乙個執行緒在搶,所以互斥並不保證合理。

多個執行流對鎖資源進行爭搶訪問,但是因為訪問推進順序不當,造成互相等到最終導致程式流程無法繼續推進,這時候就造成了死鎖。

死鎖實際是一種程式流程無法繼續推進,卡在某個位置的一種概念。

死鎖產生的必要條件:

1.互斥條件

2.不可剝奪條件:我加的鎖,別人不能解,只有我能解鎖

3.請求與保持條件:我加了a鎖,然後去請求b鎖;如果不能對b加鎖,則也不釋放a鎖

4.環路等待條件:我加了a鎖,然後去請求b鎖,另乙個人加了b鎖,然後去請求a鎖。

死鎖的預防:破壞死鎖產生的必要條件(主要避免3和4兩個條件的產生)

死鎖的避免:銀行家演算法

互斥並不保證合理/同步並不保證安全

同步的實現:通過條件判斷實現臨界資源訪問的合理性–條件變數

條件變數:向外提供了乙個使執行緒等待的介面和喚醒執行緒的介面+pcb的等待佇列

當前是否滿足獲取資源的條件,若不滿足,則讓執行流等待,等到滿足條件能夠獲取的時候再喚醒執行流

實現同步:兩個功能介面:讓執行流等待的介面和喚醒執行流的介面

使用介面介紹:

定義條件變數----pthread_cond_t cond;

初始化條件變數

pthread_cond_init(pthread_cond_t cond,pthread_condattr_t attr)

pthread_cond_t cond=pthread_cond_initializer;

若資源獲取條件不滿足時呼叫介面進行阻塞等待:條件變數是搭配互斥鎖一起使用的

pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex);-----一直死等別人的喚醒

pthread_cond_timedwait(pthread_cond_t *,pthread_mutex_t *,struct timespec *)----設定阻塞超時時間的等待介面

喚醒執行緒的介面:

pthread_cond_signal(pthread_cond_t *)----喚醒至少乙個等待的執行緒

pthread_cond_broadcast(pthread_cond_t *)----喚醒所有等待的執行緒

銷毀條件變數:

pthread_cond_destroy(pthread_cond_t );

示例:

注意事項:

第一種情況:多個顧客執行緒,因為沒有飯等待,這時候乙個廚師做了一碗飯,去喚醒顧客(至少喚醒乙個),但是顧客只能有乙個加鎖,其他兩個顧客執行緒卡在加鎖這裡,吃完飯後解鎖,但是這時候加上鎖的不一定是廚師執行緒,有可能是等待的兩個顧客執行緒,那這個顧客執行緒就在沒有飯的情況下吃了一碗飯----邏輯錯誤。那麼避免這種邏輯錯誤,條件的判斷應該是乙個迴圈判斷,顧客執行緒被喚醒加鎖成功後重新判斷有沒有飯,沒有休眠,有就等待

第二種情況:乙個顧客執行緒吃完飯,一條佇列上有3個廚師執行緒,顧客執行緒進入佇列,廚師做好飯,喚醒的可能就不是顧客執行緒,被喚醒的廚師執行緒發現有飯,重新休眠,導致程式阻塞。解決方案----不同角色的執行緒應該掛在不同的等待佇列上等待,喚醒的時候,就有目的性的喚醒,因此多個角色需要使用多個條件變數。

多執行緒 執行緒安全

原因 當多個執行緒同時共享,同乙個全域性變數或靜態變數。做寫的操作時,可能發生資料衝突問題,也就是執行緒安全問題。但是做讀操作是不會發生資料衝突問題。解決方案 方式一 內建鎖synchronized synchronized保證執行緒原子性,當執行緒進入方法的時候,自動獲取鎖,一旦鎖被其它執行緒獲取...

多執行緒 執行緒安全

public class unsafethread t.start while thread.activecount 1 system.out.println sum 1 從主記憶體中講sum變數複製到執行緒的工作記憶體 2 在工作記憶體中修改變數 1操作 3 將sum變數從執行緒的工作記憶體寫回到...

多執行緒安全

專案中需要在多執行緒環境下,輸出日誌到標準輸出,以下是實現過程。首先,我們需要乙個鎖類,能夠自動初始化,並且降低耦合。locker.h created on apr 14,2012 author joan ifndef locker h define locker h include option....