You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何我的多线程代码未产生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。

这两种情况都不会触发竞态,因为线程切换没发生在“读-改-写”的中间步骤里。

如何触发竞态条件

要稳定复现竞态,你需要增加线程切换的概率,比如:

  1. 循环执行操作:让每个线程重复多次修改资源数,放大冲突的可能性;
  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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 14:45:42