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

使用线程时为何某条指令有时会执行两次(C语言)

问题分析

输入字符'f'时输出语句重复执行的核心原因是无同步的共享变量访问引发竞态条件,以及线程退出逻辑错误:

  • 全局变量att和c属于线程间共享资源,但代码未使用任何同步机制(如互斥锁),导致线程无法保证读取到变量的最新值,可能出现指令重排序、缓存不一致的情况,使得write线程误判循环条件。
  • 线程中调用exit(0)会直接终止整个进程,而非仅退出当前线程,这会打乱线程间的正常执行时序,增加竞态发生的概率。
  • write线程的do-while循环先执行输出操作再判断退出条件,当c已为'f'时,仍会先执行一次输出,若此时因同步问题导致线程重复进入循环,就会出现两次输出。
修复后的代码

使用互斥锁+条件变量保证线程同步,同时修正线程退出逻辑:

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

char c;
// 互斥锁保证共享变量原子访问
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
// 条件变量实现线程间等待/通知
pthread_cond_t cond_read = PTHREAD_COND_INITIALIZER;
pthread_cond_t cond_write = PTHREAD_COND_INITIALIZER;
// 标记当前可执行的操作:1=允许读取,0=允许写入
int can_read = 1;

void* th_read(void *k){    
    do {    
        pthread_mutex_lock(&mutex);
        // 等待读取权限
        while(!can_read) {
            pthread_cond_wait(&cond_read, &mutex);
        }
        printf("type a character : ");
        scanf(" %c",&c);
        // 切换为可写入状态,通知write线程
        can_read = 0;
        pthread_cond_signal(&cond_write);
        pthread_mutex_unlock(&mutex);
        
    }while(c != 'f');
    
    // 仅退出当前线程,不终止整个进程
    pthread_exit(NULL);
}

void* th_write(void *k){    
    do {    
        pthread_mutex_lock(&mutex);
        // 等待写入权限
        while(can_read) {
            pthread_cond_wait(&cond_write, &mutex);
        }
        // 仅当输入不是'f'时才输出,避免退出前的多余打印
        if(c != 'f') {
            printf("character typed is : %c \n",c);
        }
        // 切换为可读取状态,通知read线程
        can_read = 1;
        pthread_cond_signal(&cond_read);
        pthread_mutex_unlock(&mutex);
        
    }while(c != 'f');
    
    pthread_exit(NULL);
}

int main(){
    int i;
    pthread_t pth_id[2];
    
    pthread_create(&pth_id[0], NULL, th_read, NULL);
    printf("Main: reading thread created with id = %ld\n", (long)pth_id[0]);
    
    pthread_create(&pth_id[1], NULL, th_write, NULL);
    printf("Main: writing thread created with id= %ld\n", (long)pth_id[1]);
    
    for(i = 0; i < 2; i++) {
        pthread_join(pth_id[i], NULL);
    }
    
    // 销毁同步对象
    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond_read);
    pthread_cond_destroy(&cond_write);
    
    return 0;
}
关键修复点
  • 同步机制:用互斥锁确保共享变量的原子访问,条件变量实现线程间有序的等待与唤醒,彻底消除竞态条件。
  • 线程退出:用pthread_exit(NULL)替代exit(0),仅退出当前线程,保证其他线程能正常执行退出逻辑。
  • 输出逻辑:write线程在输出前判断c是否为'f',避免退出前的多余输出。
  • 类型修正:将pthread_t转换为long类型打印,避免编译警告。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 05:13:15