我正在Linux上同步读者和编写者进程。
我有0个或更多的进程(读者)需要睡觉,直到他们被唤醒,阅读资源,重新入睡等等。请注意我不知道有多少阅读器进程随时都在运行。 我有一个进程(作者)写入资源,唤醒读者并完成其业务直到另一个资源准备好(详细地说,我开发了一个没有饥饿的读者 - 写作者解决方案,但这并不重要。)
为了实现睡眠/唤醒机制,我使用Posix条件值pthread_cond_t。客户端调用pthread_cond_wait()对变量进行休眠,而服务器执行pthread_cond_broadcast()将其全部唤醒。正如手册所说,我通过锁定/解锁相关的pthread互斥锁来围绕这两个调用。
条件变量和互斥体在服务器中初始化,并通过共享内存区域在进程之间共享(因为我不使用线程,但是使用单独的进程),我确信我的内核/系统调用支持它(因为我查了_POSIX_THREAD_PROCESS_SHARED)。
第一个客户端进程会完美地睡眠和唤醒。当我启动第二个进程时,它会阻塞其pthread_cond_wait()并且永远不会唤醒,即使我确定(通过日志)调用了pthread_cond_broadcast()。
如果我杀了第一个进程,并启动另一个进程,它就可以完美运行。换句话说,条件变量pthread_cond_broadcast()似乎一次只唤醒一个进程。如果多个进程在同一个共享条件变量上等待,则只有第一个进程能够正常唤醒,而其他进程似乎忽略了广播。
为什么会这样?如果我发送pthread_cond_broadcast(),每个等待进程都应该唤醒,而不仅仅是一个(但是,并不总是相同)。
答案 0 :(得分:4)
你的condvar和mutex都有set the PTHREAD_PROCESS_SHARED
attribute吗?
对于Linux ,请参阅以下man
页:
pthread_mutexattr_init
(带样本)pthread_mutexattr_setpshared
pthread_condattr_init
pthread_condattr_setpshared
方法,类型,常量等通常在/usr/include/pthread.h
,/usr/include/nptl/pthread.h
中定义。
答案 1 :(得分:3)
在您的流程实际调用pthread_cond_wait()
之前,您是否测试了某些条件?我问,因为这是一个非常常见的错误:您的流程必须不致电wait()
,除非您确定某个流程会调用signal()
(或broadcast()
) 后
汇总此代码(来自pthread_cond_wait
手册页):
pthread_mutex_lock(&mut);
while (x <= y) {
pthread_cond_wait(&cond, &mut);
}
/* operate on x and y */
pthread_mutex_unlock(&mut);
如果省略while
测试,并且只要你的(x <= y)条件为真,就从其他进程发出信号,它将无法工作,因为信号只唤醒已经在等待的进程。如果在其他进程调用signal()
之前调用wait()
,则信号将丢失,等待进程将永远等待。
编辑:关于while循环。
当您从另一个进程发信号通知一个进程时,它被设置在“就绪列表”上但不一定被安排,并且您的条件(x <= y)可能会再次改变,因为没有人持有该锁。这就是为什么每次你要等待时都要检查自己的状况。它应始终为wakeup -> check if the condition is still true -> do work
。
希望很清楚。
答案 2 :(得分:1)
文档说它应该有用......你确定它与其他线程看到的条件值相同吗?
这是opengroup.org的示例代码:
pthread_cond_wait(mutex, cond):
value = cond->value; /* 1 */
pthread_mutex_unlock(mutex); /* 2 */
pthread_mutex_lock(cond->mutex); /* 10 */
if (value == cond->value) { /* 11 */
me->next_cond = cond->waiter;
cond->waiter = me;
pthread_mutex_unlock(cond->mutex);
unable_to_run(me);
} else
pthread_mutex_unlock(cond->mutex); /* 12 */
pthread_mutex_lock(mutex); /* 13 */
pthread_cond_signal(cond):
pthread_mutex_lock(cond->mutex); /* 3 */
cond->value++; /* 4 */
if (cond->waiter) { /* 5 */
sleeper = cond->waiter; /* 6 */
cond->waiter = sleeper->next_cond; /* 7 */
able_to_run(sleeper); /* 8 */
}
pthread_mutex_unlock(cond->mutex); /* 9 */
答案 3 :(得分:0)
最后一张海报所说的是正确的。整个cond变量情况正常工作的关键是cond-var在等待之前没有发出信号。它严格地是当其他人(单人或多人)等待时使用的信号。当没有人在等待时,它实际上是一个NOP。哪,顺便说一下,我不相信它应该如何工作,但它是如何运作的。
拉里