5

I'm trying to write very simple multi threading program just to get the catch of it but I fail to understand what exactly is wrong in one of the cases. So:

#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>

char string[100];
pthread_t thr_id_rd;
pthread_t thr_id_wr;
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond, cond1;
int read = 0;

void *thread_rd()
{
    pthread_mutex_lock(&lock);
    while (1) {
        pthread_cond_wait(&cond, &lock);
        printf("rd: entered: %s\n", string);
        pthread_cond_signal(&cond1);
    }
    pthread_mutex_unlock(&lock);
}

void *thread_wr()
{
    pthread_mutex_lock(&lock);
    while (1) {
        printf("wr: enter something: ");
        scanf("%s", string);
        pthread_cond_signal(&cond);
        pthread_cond_wait(&cond1, &lock);
    }
    pthread_mutex_unlock(&lock);
}

int main(int argc, char *argv[])
{
    pthread_create(&thr_id_rd, NULL, thread_rd, NULL);
    pthread_create(&thr_id_wr, NULL, thread_wr, NULL);

    pthread_join(thr_id_rd, NULL);
    pthread_join(thr_id_wr, NULL);

    return 0;
}

The above seems to work correctly. But when I edit the two threads like this:

void *thread_rd()
{
    while (1) {
        pthread_mutex_lock(&lock);
        pthread_cond_wait(&cond, &lock);
        printf("rd: entered: %s\n", string);
        pthread_cond_signal(&cond1);
        pthread_mutex_unlock(&lock);
    }
}

void *thread_wr()
{
    while (1) {
        pthread_mutex_lock(&lock);
        printf("wr: enter something: ");
        scanf("%s", string);
        pthread_cond_signal(&cond);
        pthread_cond_wait(&cond1, &lock);
        pthread_mutex_unlock(&lock);
    }
}

I'm getting undefined behavior - sometimes it's OK sometimes the program is stuck. According the man pages pthread_cond_wait must be called with mutex locked but there is no such restriction for _cond_signal (Question: What is the best practice?). So I decided to call it with mutex locked...

Obviously I'm complete newbie so please excuse my stupid question :( I'll be very grateful if someone can explain this to me...

4

1 回答 1

5

pthread 条件变量信号不是持久的。如果您在没有任何东西等待信号时发出信号,则信号将丢失。所以你可以看到这样的东西:

WR: Lock
WR: Read input
WR: Signal cond
WR: Wait for cond1 (implicitly unlocks)
RD: Lock
RD: Wait for cond (implicitly unlocks)

在这一点上你有一个死锁 - 两个线程都在等待永远不会到来的信号。

使用 condvars 的通常模式是将标志(或其他一些持久性条件)与条件变量配对。然后,您可以执行如下循环:

while (!flag) pthread_cond_wait(&cond, &lock);

要发出信号,您设置标志,然后向 condvar 发出信号以唤醒任何服务员。

在您的情况下,您实际上可以string用作您的标志 -string == NULL将唤醒条件与 . 配对cond1string != NULL配对cond. 现在,如果您的阅读器线程较晚进入锁,它会看到这一点,string != NULL而不是等待 condvar。

于 2012-11-05T03:49:13.623 回答