Linux上的pthread条件变量,异常行为

qgelzfjb  于 2022-12-11  发布在  Linux
关注(0)|答案(4)|浏览(187)

我正在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(),* 每个 * 等待进程都应该被唤醒,而不是只有一个(当然,也不总是同一个)。

50few1ms

50few1ms1#

是否已在condvar和mutex上设置了PTHREAD_PROCESS_SHARED属性?

对于Linux,请参阅以下man页面:

方法、类型、常量等通常在/usr/include/pthread.h/usr/include/nptl/pthread.h中定义。

t0ybt7op

t0ybt7op2#

在调用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循环。当你从一个进程向另一个进程发送信号时,它被设置在'' ready list ''上,但不一定被调度,并且你的条件(x〈= y)可能会再次改变,因为没有人持有锁。这就是为什么你需要在每次等待时检查你的条件。它应该总是wakeup -> check if the condition is still true -> do work
我希望天气晴朗.

oprakyz7

oprakyz73#

文档中说它应该可以工作...您确定它与其他线程正在查看的条件值相同吗?
这是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 */
qlvxas9a

qlvxas9a4#

最后一张海报说的是正确的。整个cond-variable情况正确工作的关键是cond-var在它被等待之前没有发出信号。它严格地是一个信号,当其他人(一个或多个)在等待时使用。当没有人在等待时,它实际上是一个NOP。顺便说一句,这不是我认为它应该如何工作,而是它如何工作。
拖拉机

相关问题