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

Meh*_*Meh 5 c mutex pthreads

我正在尝试编写一个非常简单的多线程程序,只是为了获得它的捕获但我无法理解其中一个案例的确切错误.所以:

#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;
}
Run Code Online (Sandbox Code Playgroud)

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

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

bdo*_*lan 5

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

WR: Lock
WR: Read input
WR: Signal cond
WR: Wait for cond1 (implicitly unlocks)
RD: Lock
RD: Wait for cond (implicitly unlocks)
Run Code Online (Sandbox Code Playgroud)

此时你有一个死锁 - 两个线程都在等待永远不会发出的信号.

condvars的通常模式是具有与条件变量配对的标志(或一些其他持久条件).然后你可以做一个循环:

while (!flag) pthread_cond_wait(&cond, &lock);
Run Code Online (Sandbox Code Playgroud)

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

在您的情况下,您实际上可以使用string作为您的旗帜 - string == NULL与唤醒条件配对cond1string != NULL配对cond.现在,如果你的读者线程迟到了锁,它会看到,string != NULL而不是等待condvar.