互斥量:
大部分情況,執行緒使用的資料都是執行緒自己區域性儲存的變數,變數的位址空間在該執行緒棧空間內,這種情況,變數歸屬單個執行緒,其他執行緒無法獲得這種變數。
多個執行緒併發的操作共享變數帶來的問題:
// 操作共享變數從而導致的執行緒安全問題
// 售票系統
#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...