在 C 語言中使用互斥鎖
本文將介紹幾種在 C 語言中使用互斥鎖的方法。
使用 pthread_mutex_t
型別和 pthread_mutex_lock
函式來守護程式碼的關鍵部分
執行緒共享地址空間,這意味著對全域性變數等共享資料的修改必須同步,否則,將出現不正確的程式行為。請注意,下面的程式碼用 pthread_create
呼叫建立了 4 個額外的執行緒,並傳遞 func3
作為它們執行的起點。func3
在 10000 次迭代 for
迴圈中逐一修改全域性變數 shared
。因此,如果四個執行緒分別將 shared
的值遞增 10000,程式應該輸出 40000。
如果執行下面的程式碼,結果將是某個隨機整數,但不是 40000。這種行為一般被歸為競賽條件,意味著給定的執行緒在訪問共享變數時沒有相互協商即同步。即,往往當它們執行迴圈
交錯時,對共享變數的訪問和儲存達到不一致,最後得出錯誤的和。
多個執行緒修改記憶體中同一個物件的程式碼部分稱為關鍵部分。一般來說,關鍵部分應該用某種型別的鎖來保護,迫使其他執行緒等到當前執行緒完成執行,並確保它們都能得到正確的增量值。Mutex 是其中一種鎖型別,可以利用它來保護關鍵部分,就像 func3
中的這個 for
迴圈一樣。
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#ifndef NUM_THREADS
#define NUM_THREADS 4
#endif
int shared = 0;
void* func3(void* param) {
printf("Incrementing the shared variable...\n");
for (int i = 0; i < 10000; ++i) {
shared += 1;
}
return 0;
}
int main() {
pthread_t threads[NUM_THREADS];
for (int i = 0; i < NUM_THREADS; ++i) {
pthread_create(&threads[i], NULL, func3, NULL);
}
for (int i = 0; i < NUM_THREADS; ++i) {
pthread_join(threads[i], NULL);
}
printf("%d\n", shared);
exit(EXIT_SUCCESS);
}
輸出:
Incrementing the shared variable...
Incrementing the shared variable...
Incrementing the shared variable...
Incrementing the shared variable...
30384
在這種情況下,我們將利用 POSIX 執行緒庫及其內建的 pthread_mutex_t
型別。pthread_mutex_t
型別變數通常被宣告為 static
儲存持續時間。互斥鎖只能在使用前應該只初始化一次。當互斥鎖被宣告為 static
時,應該使用 PTHREAD_MUTEX_INITIALIZER
巨集來初始化它。當互斥鎖被初始化後,執行緒就可以相應地使用 pthread_mutex_lock
和 pthread_mutex_unlock
函式。pthread_mutex_lock
鎖定作為唯一引數傳遞的 mutex 物件。如果互斥鎖已經被鎖定,呼叫執行緒會被阻塞,直到互斥鎖變得可用。應該呼叫 pthread_mutex_unlock
來解鎖互斥鎖。如果有執行緒在同一個互斥鎖上等待,則由排程策略決定哪個執行緒獲得物件鎖。最後,我們對四個執行緒中的每一個執行緒都呼叫 pthread_join
,並列印出整數-shared
,在這種情況下,它應該有正確的值儲存。
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#ifndef NUM_THREADS
#define NUM_THREADS 4
#endif
int shared = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void* func3(void* param) {
pthread_mutex_lock(&mutex);
printf("Incrementing the shared variable...\n");
for (int i = 0; i < 10000; ++i) {
shared += 1;
}
pthread_mutex_unlock(&mutex);
return 0;
}
int main() {
pthread_t threads[NUM_THREADS];
for (int i = 0; i < NUM_THREADS; ++i) {
pthread_create(&threads[i], NULL, func3, NULL);
}
for (int i = 0; i < NUM_THREADS; ++i) {
pthread_join(threads[i], NULL);
}
printf("%d\n", shared);
exit(EXIT_SUCCESS);
}
輸出:
Incrementing the shared variable...
Incrementing the shared variable...
Incrementing the shared variable...
Incrementing the shared variable...
40000