在 C 語言中使用互斥鎖

Jinku Hu 2023年10月12日 C C Mutex
在 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_lockpthread_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
Enjoying our tutorials? Subscribe to DelftStack on YouTube to support us in creating more high-quality video guides. Subscribe
作者: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

DelftStack.com 創辦人。Jinku 在機器人和汽車行業工作了8多年。他在自動測試、遠端測試及從耐久性測試中創建報告時磨練了自己的程式設計技能。他擁有電氣/ 電子工程背景,但他也擴展了自己的興趣到嵌入式電子、嵌入式程式設計以及前端和後端程式設計。

LinkedIn Facebook