建立 100 個執行緒,每個執行緒對全域變數 g_iTestInteger 執行 ++ 操作。理論結果應為 100,但實際執行多次發現結果為 98~99 且不固定,甚至主執行緒列印時仍有子執行緒在執行。
g_iTestInteger++ 在機器碼層級至少包含三步:讀取 → 加一 → 寫回。多執行緒並發執行時,可能發生交錯:
此外,主執行緒未等待子執行緒結束直接列印,導致結果更不可預期。
在 ProcessTask 中加入 printf 後發現:執行緒執行順序亂序,且主執行緒列印時仍有子執行緒在跑。
// 建立執行緒後 sleep(1) 等待所有執行緒結束
Sleep(1000); // 休眠 1 秒
printf("In main, TestInteger = %d", g_iTestInteger);
結果固定為 100,但屬於「碰運氣」同步,無法保證所有平台、負載下皆正確。
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void *ProcessTask(void *arg) {
pthread_mutex_lock(&mutex);
g_iTestInteger++;
pthread_mutex_unlock(&mutex);
return NULL;
}
#include <stdatomic.h>
atomic_int g_iTestInteger = 0;
// 執行緒中直接:
atomic_fetch_add_explicit(&g_iTestInteger, 1, memory_order_relaxed);
每個執行緒累加自己的區域變數,結束前用鎖或原子操作加到全域總和,減少鎖競爭。
pthread_mutex、原子操作、無鎖資料結構。pthread_join() 逐一回收,而非 sleep。#include <pthread.h>
#include <stdio.h>
#define THREAD_NUM 100
int g_iTestInteger = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void *ProcessTask(void *arg) {
pthread_mutex_lock(&mutex);
g_iTestInteger++;
pthread_mutex_unlock(&mutex);
return NULL;
}
int main() {
pthread_t threads[THREAD_NUM];
for (int i = 0; i < THREAD_NUM; i++)
pthread_create(&threads[i], NULL, ProcessTask, NULL);
for (int i = 0; i < THREAD_NUM; i++)
pthread_join(threads[i], NULL); // 正確等待
printf("Final value: %d\n", g_iTestInteger); // 穩定輸出 100
return 0;
}