執行緒安全 互斥

2021-09-25 14:58:19 字數 2055 閱讀 9912

互斥量:

大部分情況,執行緒使用的資料都是執行緒自己區域性儲存的變數,變數的位址空間在該執行緒棧空間內,這種情況,變數歸屬單個執行緒,其他執行緒無法獲得這種變數。

多個執行緒併發的操作共享變數帶來的問題:

// 操作共享變數從而導致的執行緒安全問題

// 售票系統

#include #include #include // 模擬售票

int ticket = 100;

void* route(void* args)

else

}return null;

}int main()

// 存在問題:

if 語句判斷條件為真以後,**可以併發的切換到其他執行緒

usleep 這個模擬漫長業務的過程,在這個漫長的業務過程中,可能有很多個執行緒會進入該**段

--ticket 操作本身就不是乙個原子操作

->ticket 操作對應三條彙編指令:

load :將共享變數ticket從記憶體載入到暫存器中

update : 更新暫存器裡面的值,執行-1操作

解決共享變數安全辦法:

互斥量的初始化:

// 1.靜態分配

pthread_mutex_t mutex = pthread_mutex_initializer; // 使用 pthread_ mutex_ initializer 初始化的互斥量不需要銷毀

// 2.動態分配

int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t* restrict attr);

mutex 「要初始化的互斥量」

attr 「通常置 null」

銷毀互斥量:

1.不要銷毀乙個已經加鎖的互斥量

2.已經銷毀的互斥量,要確保後面不會有執行緒再嘗試加鎖

int pthread_mutex_destroy(pthread_mutex_t *mutex);

互斥量的使用:

1.互斥量處於未鎖狀態,該函式會將互斥量鎖定,同時返回成功

2.發起函式呼叫時,其他執行緒已經鎖定互斥量,或者存在其他執行緒同時申請互斥量,但沒有競爭到互斥量,那麼pthread_ lock呼叫會陷入阻塞(執行流被掛起),等待互斥量解鎖。

// 加鎖

int pthread_mutex_lock(pthread_mutex_t* mutex); // 做阻塞加鎖,加不上阻塞

int pthread_mutex_trylock(pthread_mutex_t* mutex) // 非阻塞加鎖,加不上報錯返回

pthread_mutex_timelock(); // 限時的阻塞加鎖

// 解鎖

int pthread_mutex_unlock(pthread_mutex_t* mutex);

返回值:成功返回0,失敗返回錯誤號

加互斥鎖之後的購票系統

#include #include #include #include int ticket = 1000;

pthread_mutex_t mutex; // 定義互斥鎖變數

void* route(void* args)

else

}

return null;

}int main()

}

for (int i = 0; i < 4; ++i)

pthread_mutex_destroy(&mutex); // 銷毀互斥量

return 0;

}

互斥鎖 死鎖與執行緒安全

一 典型的兩種死鎖情形 一 執行緒自己將自己鎖住 一般情況下,如果同乙個執行緒先後兩次呼叫lock,在第二次調 用時,由於鎖已經被占用,該執行緒會掛起等待占用鎖的執行緒釋放鎖,然而鎖正是被自己占用著的,該執行緒又被掛起而沒有機會釋放鎖,因此 就永遠處於掛起等待狀態了,於是就形成了死鎖 deadloc...

執行緒 互斥鎖

include include include include include 1.靜態初始化,當動態初始化時,遮蔽靜態初始化 pthread mutex t mutex pthread mutex initializer 2.動態初始化 pthread mutex t mutex int lock...

執行緒的互斥

我們可以用關鍵字private來保證資料物件只能被本類方法訪問,所以我們只需對方法提出一套機制,來對共享的資料物件進行互斥鎖定,這套機制就是執行緒的互斥使用關鍵字synchronized,有synchronized方法和synchronized塊兩種方法。舉例 模擬對銀行賬戶的訪問款操作 packa...