5

私はそれを理解するためだけに非常に単純なマルチスレッドプログラムを作成しようとしていますが、ケースの1つで正確に何が間違っているのか理解できません。そう:

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

上記は正しく動作しているようです。しかし、次のように 2 つのスレッドを編集すると:

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

未定義の動作が発生します。問題がない場合もあれば、プログラムがスタックする場合もあります。man ページによると、pthread_cond_waitはミューテックスをロックして呼び出す必要がありますが、_cond_signal にはそのような制限はありません (質問: ベスト プラクティスは何ですか?)。そこで、ミューテックスをロックして呼び出すことにしました...

明らかに私は完全な初心者なので、愚かな質問を許してください:(誰かが私にこれを説明できればとても感謝しています...

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できます。リーダースレッドが遅れてロックに入ると、それがわかり、condvar を待機しなくなります。string == NULLcond1string != NULLcondstring != NULL

于 2012-11-05T03:49:13.623 に答える