操作共享counter的两个循环线程如何同步避免死循环?
问题根因
- 共享变量
counter的判断逻辑未放在锁保护范围内,存在竞态条件:当counter值为1时,两个线程都可能先在锁外判断counter != 0为真,进入循环块。其中一个线程先拿到锁将counter减为0后释放锁,另一个线程拿到锁后会继续将counter减为-1,后续判断counter != 0永远为真,程序陷入死循环。 - 示例代码中
counter初始值写错,需求是初始值为100,代码中写为int counter = 0,会导致线程直接不进入执行逻辑。
修复方案
调整循环逻辑,将counter的判断和修改操作全部放在锁的保护范围内,避免竞态问题,修改后代码如下:
#include <stdio.h> #include <pthread.h> #include <unistd.h> int counter = 100; // 修正初始值为100 pthread_mutex_t counter_mutex; void *Thread1(void *vargs) { while (1) { pthread_mutex_lock(&counter_mutex); // 所有对counter的读写操作都在持有锁时执行 if (counter == 0) { pthread_mutex_unlock(&counter_mutex); break; } counter--; pthread_mutex_unlock(&counter_mutex); } sleep(1); printf("Completed Thread1\n"); return NULL; } void *Thread2(void *vargs) { while (1) { pthread_mutex_lock(&counter_mutex); if (counter == 0) { pthread_mutex_unlock(&counter_mutex); break; } counter--; pthread_mutex_unlock(&counter_mutex); } sleep(1); printf("Completed Thread2\n"); return NULL; } int main(void) { pthread_t tid[2]; // 初始化互斥锁 pthread_mutex_init(&counter_mutex, NULL); // 创建工作线程 pthread_create(&tid[0], NULL, Thread1, NULL); pthread_create(&tid[1], NULL, Thread2, NULL); // 等待工作线程终止 pthread_join(tid[0], NULL); pthread_join(tid[1], NULL); // 打印最终counter值 printf("Counter is %d\n", counter); // 销毁互斥锁避免资源泄漏 pthread_mutex_destroy(&counter_mutex); return 0; }
补充说明
pthread_mutex 相关的锁操作自带内存屏障语义,能够保证共享变量在多线程间的可见性,不需要额外添加volatile关键字修饰counter。修改后程序运行时两个线程都会在counter减到0后正常退出,不会出现死循环问题。
内容的提问来源于stack exchange,提问作者Tony Hoan Trinh
相关产品推荐
相关产品推荐

