为何我的多线程代码未产生Race Condition?欲制造并用Mutex修复
为什么我的代码没出现预期的竞态条件?
我尝试制造竞态条件并用互斥锁修复,但目前代码运行一直正常,没出现竞态条件。我很疑惑:这段代码难道不该产生竞态条件吗?
以下是我的代码:
#define MAX_RESOURCES 10 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <pthread.h> int available_resources = 10; void* decrease_count(void *count); void* increase_count(void *count); pthread_t thread1; pthread_t thread2; int main () { int decrease = 8; int increase = 3; pthread_create(&thread1, NULL, decrease_count, (void*) &decrease); pthread_create(&thread2, NULL, increase_count, (void*) &increase); pthread_join(thread1, NULL); pthread_join(thread2, NULL); printf("amount of resource: %d",available_resources); return 0; } void* decrease_count(void *count){ available_resources -= *((int *)count); return NULL; } void* increase_count(void *count){ if(available_resources + *((int *)count) <= MAX_RESOURCES) { available_resources += *((int *)count); return 0; } return NULL; }
问题分析
首先要明确:竞态条件不是必然会出现的,它是概率性的,完全依赖操作系统的线程调度时机。你的代码里两个线程的操作都极其简短——只是单次的加减运算,操作系统的调度器很可能还没来得及切换线程,其中一个线程就已经完成了所有操作。比如:
- 线程1先执行完
decrease_count,available_resources变成2,之后线程2执行increase_count,判断2+3≤10,最终结果是5; - 或者线程2先执行,判断10+3>10,不做任何操作,之后线程1执行减8,最终结果是2。
这两种情况都不会触发竞态,因为线程切换没发生在“读-改-写”的中间步骤里。
如何触发竞态条件
要稳定复现竞态,你需要增加线程切换的概率,比如:
- 循环执行操作:让每个线程重复多次修改资源数,放大冲突的可能性;
- 插入延迟:在修改资源的前后加入
usleep(1)这类延迟,给调度器切换线程的机会。
比如修改后的decrease_count和increase_count:
void* decrease_count(void *count){ // 循环1000次,增加冲突概率 for(int i=0; i<1000; i++){ usleep(1); available_resources -= *((int *)count); } return NULL; } void* increase_count(void *count){ // 循环1000次,增加冲突概率 for(int i=0; i<1000; i++){ usleep(1); if(available_resources + *((int *)count) <= MAX_RESOURCES) { available_resources += *((int *)count); } } return NULL; }
运行这个版本,你大概率会看到available_resources的结果不符合预期,这就是竞态条件导致的。
用互斥锁修复
要解决竞态,需要用互斥锁保护所有对available_resources的读写操作:
#define MAX_RESOURCES 10 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <pthread.h> int available_resources = 10; pthread_mutex_t resource_mutex; // 定义互斥锁 void* decrease_count(void *count); void* increase_count(void *count); pthread_t thread1; pthread_t thread2; int main () { int decrease = 8; int increase = 3; pthread_mutex_init(&resource_mutex, NULL); // 初始化互斥锁 pthread_create(&thread1, NULL, decrease_count, (void*) &decrease); pthread_create(&thread2, NULL, increase_count, (void*) &increase); pthread_join(thread1, NULL); pthread_join(thread2, NULL); pthread_mutex_destroy(&resource_mutex); // 销毁互斥锁 printf("amount of resource: %d",available_resources); return 0; } void* decrease_count(void *count){ for(int i=0; i<1000; i++){ pthread_mutex_lock(&resource_mutex); // 加锁 available_resources -= *((int *)count); pthread_mutex_unlock(&resource_mutex); // 解锁 usleep(1); } return NULL; } void* increase_count(void *count){ for(int i=0; i<1000; i++){ pthread_mutex_lock(&resource_mutex); // 加锁 if(available_resources + *((int *)count) <= MAX_RESOURCES) { available_resources += *((int *)count); } pthread_mutex_unlock(&resource_mutex); // 解锁 usleep(1); } return NULL; }
这样不管线程怎么调度,同一时间只有一个线程能访问available_resources,彻底避免竞态条件。
内容的提问来源于stack exchange,提问作者ken d
相关产品推荐
相关产品推荐

