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

使用pthread条件变量与互斥量实现线程屏障的运行异常问题

Barrier实现死锁问题修复与持续运行改造

问题分析

你的Barrier类wait方法存在逻辑错误,导致首次屏障通过后线程死锁:

  • 最后一个线程到达屏障时,将waiting重置为0并广播条件变量
  • 其他被唤醒的线程检查while (waiting < num_threads),此时waiting已被设为0,条件成立会再次进入pthread_cond_wait,永远无法退出等待
  • 只有最后一个线程能继续执行后续代码,其他线程都卡在wait中,导致程序不再打印后续屏障信息

修复后的Barrier实现

添加**代次(generation)**变量区分不同轮次的屏障,避免waiting重置导致的判断混乱:

#include <pthread.h>
#include <iostream>
#include <unistd.h> // 用于sleep

class Barrier {
public:
    explicit Barrier(int num_threads) : num_threads(num_threads), waiting(0), generation(0) {
        pthread_mutex_init(&mutex, nullptr);
        pthread_cond_init(&cond, nullptr);
    }

    ~Barrier() {
        pthread_mutex_destroy(&mutex);
        pthread_cond_destroy(&cond);
    }

    void wait() {
        pthread_mutex_lock(&mutex);

        const int current_gen = generation;
        ++waiting;

        if (waiting == num_threads) {
            // 最后一个线程到达,更新代次并唤醒所有线程
            generation++;
            waiting = 0;
            pthread_cond_broadcast(&cond);
        } else {
            // 等待直到当前轮次的屏障完成(代次变化)
            while (current_gen == generation) {
                pthread_cond_wait(&cond, &mutex);
            }
        }

        pthread_mutex_unlock(&mutex);
    }

    // 输出互斥锁,解决cout线程安全问题
    pthread_mutex_t& getCoutMutex() {
        return cout_mutex;
    }

private:
    int num_threads;
    int waiting;
    int generation; // 标记屏障的轮次
    pthread_mutex_t mutex;
    pthread_cond_t cond;
    pthread_mutex_t cout_mutex = PTHREAD_MUTEX_INITIALIZER; // 同步cout输出
};

改造线程函数实现持续运行

将固定循环改为无限循环,添加小延迟避免输出过载,同时用互斥锁同步std::cout:

void* threadFunction(void* arg) {
    Barrier* barrier = static_cast<Barrier*>(arg);
    pthread_mutex_t& cout_mutex = barrier->getCoutMutex();
    int barrier_count = 0;

    while (true) {
        // 同步输出,避免乱序
        pthread_mutex_lock(&cout_mutex);
        std::cout << "Thread " << pthread_self() << " at barrier " << barrier_count << std::endl;
        pthread_mutex_unlock(&cout_mutex);

        barrier->wait();

        pthread_mutex_lock(&cout_mutex);
        std::cout << "Thread " << pthread_self() << " passed barrier " << barrier_count << std::endl;
        pthread_mutex_unlock(&cout_mutex);

        barrier_count++;
        sleep(1); // 延迟1秒,降低输出频率
    }

    return nullptr;
}

主函数保持不变

主函数负责创建线程并等待(线程为无限循环,需用户手动终止程序,比如Ctrl+C):

int main() {
    const int num_threads = 5;
    pthread_t threads[num_threads];
    Barrier barrier(num_threads);

    for (int i = 0; i < num_threads; ++i) {
        pthread_create(&threads[i], nullptr, threadFunction, &barrier);
    }

    for (int i = 0; i < num_threads; ++i) {
        pthread_join(threads[i], nullptr);
    }

    return 0;
}

关键修改点说明

  1. 代次变量:用generation标记每一轮屏障,线程只等待当前轮次完成,不会因waiting重置而误判
  2. 输出同步:添加cout_mutex解决多线程下std::cout输出乱序问题
  3. 无限循环:将线程函数的固定循环改为while(true),配合sleep实现持续打印,直到用户主动终止程序

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 19:20:00