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

如何解决多线程竞态条件?不用sleep如何保证全局变量var输出稳定

问题根源

你遇到的现象是典型的线程执行顺序不确定导致的竞态条件:调用pthread_create仅会向操作系统注册新的可调度线程,并不会保证新线程会立刻抢占主线程的CPU时间片执行,所以var的取值完全取决于主线程执行printf("var=%d",var);和新线程执行var = 1;的先后调度顺序,自然会出现两种结果。

不使用sleep的鲁棒解决方案

有三种常用的工业级实现方式,都是靠线程同步原语保证执行顺序,不会依赖不确定的调度延迟:

方案1:调整pthread_join的调用位置

pthread_join本身就会阻塞主线程,直到目标线程执行结束。只要把打印var的逻辑放到pthread_join之后,就可以100%保证拿到线程修改后的结果:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

int var = -1; // 全局变量
  
void *myThreadFun(void *vargp)
{
    var = 1;
    return NULL;
}
   
int main()
{
    pthread_t thread_id;
    printf("Before Thread\n");
    pthread_create(&thread_id, NULL, myThreadFun, NULL);

    // 先等待线程执行结束再读取var
    pthread_join(thread_id, NULL);
    printf("var=%d\n",var);

    printf("After Thread\n");
    exit(0);
}

适用场景:不需要在主线程中做其他并行操作,只需要拿到线程执行后的结果。

方案2:使用条件变量做执行状态同步

如果主线程在创建新线程之后还有其他并行任务要做,不能直接阻塞等线程结束,可以用条件变量+互斥锁的组合,标记线程的执行状态:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

int var = -1; // 全局变量
int thread_done = 0; // 线程执行完成标记
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
  
void *myThreadFun(void *vargp)
{
    pthread_mutex_lock(&mutex);
    var = 1;
    thread_done = 1;
    pthread_cond_signal(&cond); // 通知主线程状态更新
    pthread_mutex_unlock(&mutex);
    return NULL;
}
   
int main()
{
    pthread_t thread_id;
    printf("Before Thread\n");
    pthread_create(&thread_id, NULL, myThreadFun, NULL);

    // 这里可以插入主线程需要并行执行的其他代码

    // 等待线程执行完成的信号
    pthread_mutex_lock(&mutex);
    while(!thread_done) {
        pthread_cond_wait(&cond, &mutex);
    }
    printf("var=%d\n",var);
    pthread_mutex_unlock(&mutex);

    pthread_join(thread_id, NULL);
    printf("After Thread\n");
    exit(0);
}

适用场景:主线程有并行任务需要执行,不需要立刻等待线程结束,可以灵活控制等待时机。

方案3:使用POSIX信号量做同步

信号量的逻辑更简单,适合做单对单的执行顺序同步:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>

int var = -1; // 全局变量
sem_t sem;
  
void *myThreadFun(void *vargp)
{
    var = 1;
    sem_post(&sem); // 发送信号量,通知主线程修改完成
    return NULL;
}
   
int main()
{
    pthread_t thread_id;
    sem_init(&sem, 0, 0); // 初始化信号量初始值为0
    printf("Before Thread\n");
    pthread_create(&thread_id, NULL, myThreadFun, NULL);

    // 这里可以插入主线程需要并行执行的其他代码

    sem_wait(&sem); // 阻塞等待信号量,直到线程修改完成
    printf("var=%d\n",var);

    pthread_join(thread_id, NULL);
    sem_destroy(&sem);
    printf("After Thread\n");
    exit(0);
}

适用场景:轻量级同步场景,代码比条件变量更简洁。

内容的提问来源于stack exchange,提问作者Learner09

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.11 09:09:02