pthread互斥锁定/解锁时(1)

时间:2012-11-04 12:58:11

标签: c pthreads mutex

我正在尝试编写非常简单的多线程程序,只是为了得到它的捕获但我无法理解其中一个案例中究竟出了什么问题。所以:

#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;
}

以上似乎工作正常。但是当我编辑这样的两个线程时:

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);
    }
}

我正在接受未定义的行为 - 有时它可以保存程序。根据手册页pthread_cond_wait 必须在锁定互斥锁的情况下调用,但对_cond_signal没有这样的限制(问题:最佳做法是什么?)。所以我决定用互斥锁锁定它...

显然我是新手,所以请原谅我的愚蠢问题:( 如果有人能向我解释,我将非常感激......

1 个答案:

答案 0 :(得分: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配对的唤醒条件与{{1}配对}。现在,如果你的读者线程迟到了,它会看到cond而不是等待condvar。