文章目錄
- 案例描述1
- 代碼實現
- 代碼解釋
- 案例背景2
- 代碼實現
- 代碼解析
- 關鍵概念總結
- 擴展練習
案例描述1
我們將模擬一個簡單的售票系統,其中有兩個售票窗口同時出售100張票。為了確保不會賣出超過100張票,并且不會出現賣票時的競態條件(race condition),我們將使用互斥鎖來保護共享資源——剩余票數。
代碼實現
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>#define NUM_TICKETS 100
#define NUM_THREADS 2int tickets = NUM_TICKETS;
pthread_mutex_t mutex;void* sell_tickets(void* arg) {while (1) {pthread_mutex_lock(&mutex); // 獲取互斥鎖if (tickets > 0) {printf("Thread %ld sold ticket: %d\n", (long)arg, tickets);tickets--;pthread_mutex_unlock(&mutex); // 釋放互斥鎖} else {pthread_mutex_unlock(&mutex); // 釋放互斥鎖break; // 如果沒有票了,退出循環}// 模擬線程間的切換,增加并發沖突的可能性// 可以通過注釋掉下面這行代碼來查看效果usleep(100); // 線程休眠100微秒}return NULL;
}int main() {pthread_t threads[NUM_THREADS];// 初始化互斥鎖if (pthread_mutex_init(&mutex, NULL) != 0) {printf("Mutex init failed\n");return -1;}// 創建兩個線程for (int i = 0; i < NUM_THREADS; i++) {if (pthread_create(&threads[i], NULL, sell_tickets, (void*)(intptr_t)(i + 1)) != 0) {printf("Thread creation failed\n");return -1;}}// 等待所有線程完成for (int i = 0; i < NUM_THREADS; i++) {pthread_join(threads[i], NULL);}// 銷毀互斥鎖pthread_mutex_destroy(&mutex);printf("All tickets have been sold.\n");return 0;
}
代碼解釋
pthread_mutex_t mutex;
:定義了一個互斥鎖變量。pthread_mutex_lock(&mutex);
和pthread_mutex_unlock(&mutex);
:分別用于獲取和釋放互斥鎖。當一個線程獲取到互斥鎖后,其他試圖獲取同一互斥鎖的線程將被阻塞,直到第一個線程釋放該鎖。usleep(100);
:讓當前線程暫停一段時間,模擬線程間的時間片輪轉,以便觀察到并發沖突的情況。如果注釋掉這一行,可能會減少并發沖突的機會,因為線程可能在執行完一次賣票操作前不會被打斷。pthread_create(&threads[i], NULL, sell_tickets, (void*)(intptr_t)(i + 1));
:創建新線程并開始執行sell_tickets
函數。
通過這個例子,您可以清楚地看到如何在線程之間安全地共享資源以及如何避免競態條件。請注意,在實際應用中,需要根據具體情況調整互斥鎖的應用范圍,以最小化鎖的粒度,從而提高程序的效率。
好的!我將通過一個詳細的嵌入式案例,幫助你理解 線程創建、同步互斥和互斥鎖 的概念。我們將使用 POSIX 線程(pthread)庫 在 Linux 環境下實現,這是嵌入式開發中常用的多線程編程方法。
案例背景2
假設我們有一個嵌入式系統,需要同時采集傳感器數據(如溫度)和進行數據處理。為了避免數據競爭,我們需要:
- 創建兩個線程:一個負責采集數據,另一個負責處理數據。
- 使用 互斥鎖(Mutex) 保護共享數據(傳感器數據)。
代碼實現
#include <stdio.h>
#include <pthread.h>
#include <unistd.h> // 用于 sleep 函數// 定義共享數據
int sensor_data = 0;// 定義互斥鎖
pthread_mutex_t mutex;// 線程1:采集傳感器數據
void *sensor_thread(void *arg) {while (1) {pthread_mutex_lock(&mutex); // 加鎖sensor_data++; // 修改共享數據printf("Sensor采集數據: %d\n", sensor_data);pthread_mutex_unlock(&mutex); // 解鎖sleep(1); // 模擬采集耗時}return NULL;
}// 線程2:處理傳感器數據
void *process_thread(void *arg) {while (1) {pthread_mutex_lock(&mutex); // 加鎖int data = sensor_data; // 讀取共享數據printf("Process處理數據: %d\n", data);pthread_mutex_unlock(&mutex); // 解鎖sleep(2); // 模擬處理耗時}return NULL;
}int main() {pthread_t tid1, tid2;// 初始化互斥鎖pthread_mutex_init(&mutex, NULL);// 創建兩個線程pthread_create(&tid1, NULL, sensor_thread, NULL);pthread_create(&tid2, NULL, process_thread, NULL);// 等待線程結束(實際中可能需要信號量控制)pthread_join(tid1, NULL);pthread_join(tid2, NULL);// 銷毀互斥鎖pthread_mutex_destroy(&mutex);return 0;
}
代碼解析
-
共享數據與互斥鎖
sensor_data
是共享的全局變量,會被兩個線程同時訪問。pthread_mutex_t mutex
定義了一個互斥鎖,用于保護對sensor_data
的訪問。
-
線程函數
sensor_thread
:模擬傳感器數據采集,每次對sensor_data
加1。process_thread
:模擬數據處理,讀取sensor_data
的值。- 在訪問共享數據前,通過
pthread_mutex_lock
加鎖;操作完成后,通過pthread_mutex_unlock
解鎖。
-
主函數
- 初始化互斥鎖
pthread_mutex_init
。 - 創建兩個線程
pthread_create
。 - 等待線程結束
pthread_join
(實際項目中可能需要更復雜的同步機制)。
- 初始化互斥鎖
關鍵概念總結
-
互斥鎖(Mutex)
- 用于保護共享資源,確保同一時間只有一個線程訪問。
- 操作:
lock
(加鎖) → 臨界區操作 →unlock
(解鎖)。
-
線程同步
- 通過互斥鎖協調多個線程的執行順序,避免數據競爭(Data Race)。
-
嵌入式場景注意事項
- 避免死鎖:確保加鎖后一定會解鎖。
- 最小化臨界區:減少鎖的持有時間,提高系統實時性。
擴展練習
- 嘗試移除互斥鎖,觀察數據不一致的現象。
- 添加第三個線程(如數據上傳線程),進一步練習多線程同步。
- 研究其他同步機制(如信號量、條件變量)。