使用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; }
关键修改点说明
- 代次变量:用
generation标记每一轮屏障,线程只等待当前轮次完成,不会因waiting重置而误判 - 输出同步:添加
cout_mutex解决多线程下std::cout输出乱序问题 - 无限循环:将线程函数的固定循环改为
while(true),配合sleep实现持续打印,直到用户主动终止程序
内容的提问来源于stack exchange,提问作者Khalid Abdallah
相关产品推荐
相关产品推荐

