共享内存中Condition Variable无法唤醒休眠进程问题求助
问题分析与解决方法
核心问题
你遇到的问题根源在于**std::mutex和std::condition_variable不是进程间同步原语**,它们的设计目标是同一进程内的线程同步,内部状态(如等待队列、线程标识)属于进程私有数据。跨进程共享内存使用时,两个进程的同步原语实例无法感知彼此的状态,导致P2的wait调用永远无法被P1的notify唤醒。
修复方案
改用支持进程间同步的POSIX原语(pthread_mutex_t和pthread_cond_t),通过配置进程共享属性实现跨进程同步,具体修改如下:
1. 修改共享内存结构体定义
替换标准库同步对象为POSIX同步类型:
#include <pthread.h> struct data_in_shm { int stuff; pthread_mutex_t mutex; pthread_cond_t cond; };
2. 初始化共享内存时配置进程共享属性
在创建并映射共享内存后,初始化同步原语的进程共享属性:
// P1中创建共享内存并映射完成后执行 pthread_mutexattr_t mutex_attr; pthread_mutexattr_init(&mutex_attr); // 设置为进程间共享 pthread_mutexattr_setpshared(&mutex_attr, PTHREAD_PROCESS_SHARED); pthread_mutex_init(&shm_data->mutex, &mutex_attr); pthread_mutexattr_destroy(&mutex_attr); pthread_condattr_t cond_attr; pthread_condattr_init(&cond_attr); pthread_condattr_setpshared(&cond_attr, PTHREAD_PROCESS_SHARED); pthread_cond_init(&shm_data->cond, &cond_attr); pthread_condattr_destroy(&cond_attr); shm_data->stuff = 0; // 初始化变量
3. 修改P1的唤醒逻辑
替换标准库锁操作为POSIX mutex调用:
void wake_thread(data_in_shm* shm_data) { while (true) { sleep(1); pthread_mutex_lock(&shm_data->mutex); printf("P1: stuff is %d\n", shm_data->stuff); pthread_cond_signal(&shm_data->cond); // 唤醒等待的进程/线程 pthread_mutex_unlock(&shm_data->mutex); } }
4. 修改P2的等待递增逻辑
替换为POSIX同步操作,同时添加虚假唤醒防护:
void increment_thread(data_in_shm* shm_data) { while (true) { pthread_mutex_lock(&shm_data->mutex); // 等待唤醒,自动释放锁,唤醒后重新获取锁 pthread_cond_wait(&shm_data->cond, &shm_data->mutex); shm_data->stuff++; printf("P2: incremented stuff to %d\n", shm_data->stuff); pthread_mutex_unlock(&shm_data->mutex); } }
5. 编译时链接pthread库
编译命令需添加-lpthread参数:
g++ p1.cpp -o p1 -lpthread g++ p2.cpp -o p2 -lpthread
额外注意事项
- 虚假唤醒:
pthread_cond_wait可能因系统原因触发虚假唤醒,若业务逻辑需要,可在等待前添加条件判断(比如检查是否有实际的唤醒信号)。 - 资源清理:使用完共享内存后,需调用
pthread_mutex_destroy、pthread_cond_destroy销毁同步原语,并正确释放共享内存资源,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Daniel Enright
相关产品推荐
相关产品推荐

