20

pthread_cond_wait の基本を学ぼうとしています。すべての用法で、私はどちらかを見ます

if(cond is false)
   pthread_cond_wait

また

while(cond is false)
   pthread_cond_wait

私の質問は、条件が false であるという理由だけで cond_wait を使用したいということです。それでは、if/while ループを明示的に配置するという苦労をしなければならないのはなぜですか。cond_wait直接ヒットする前に if/while チェックを行わないと、まったく返されないことを理解できます。この目的を解決するためだけの状態チェックですか、それとも別の意味がありますか。不要な条件待機を解決する場合、条件チェックを入れて cond_wait を回避することは、ポーリングに似ていますか?? 私はこのように cond_wait を使用しています。

void* proc_add(void *name){
    struct vars *my_data = (struct vars*)name;
    printf("In thread Addition and my id = %d\n",pthread_self());
    while(1){
    pthread_mutex_lock(&mutexattr);
    while(!my_data->ipt){  // If no input get in
            pthread_cond_wait(&mutexaddr_add,&mutexattr);  // Wait till signalled
            my_data->opt = my_data->a + my_data->b;
            my_data->ipt=1;
            pthread_cond_signal(&mutexaddr_opt);
    }
    pthread_mutex_unlock(&mutexattr);
    if(my_data->end)
            pthread_exit((void *)0);
    }
}

ロジックは、入力が利用可能な場合はいつでもデータを処理するように入力スレッドに要求し、出力スレッドにそれを印刷するように通知します。

4

2 に答える 2

29

pthread_cond_wait待機している条件に達していなくても、呼び出したスレッドが起動する可能性があるため、while ループが必要です。この現象を「スプリアス ウェイクアップ」と呼びます。

これはバグではなく、条件変数の実装方法です。

これは man ページにもあります。

pthread_cond_timedwait() または pthread_cond_wait() 関数からの偽のウェイクアップが発生する場合があります。pthread_cond_timedwait() または pthread_cond_wait() からの戻りは、この述部の値について何も意味しないため、そのような戻り時に述部を再評価する必要があります

実際のコードに関する更新:

void* proc_add(void *name) 
{
    struct vars *my_data = (struct vars*)name;

    printf("In thread Addition and my id = %d\n",pthread_self());

    while(1) {

        pthread_mutex_lock(&mutexattr);

        while(!my_data->ipt){  // If no input get in
            pthread_cond_wait(&mutexaddr_add,&mutexattr);  // Wait till signalled
        }

        my_data->opt = my_data->a + my_data->b;
        my_data->ipt=1;
        pthread_cond_signal(&mutexaddr_opt);

        pthread_mutex_unlock(&mutexattr);

        if(my_data->end)
            pthread_exit((void *)0);
        }
    }
}
于 2012-10-29T13:18:57.047 に答える
14

条件変数のシグナルはキューに入れられない (条件変数はセマフォではない) ため、待機する前にミューテックスの下で条件をテストする必要があります。つまり、スレッドがその条件変数でpthread_cond_signal()ブロックされていないときにスレッドが呼び出された場合、シグナルは何もしません。pthread_cond_wait()

これは、1 つのスレッドが条件を設定した場合、次のことを意味します。

pthread_mutex_lock(&m);
cond = true;
pthread_cond_signal(&c);
pthread_mutex_unlock(&m);

そして別のスレッドが無条件に待機しました:

pthread_mutex_lock(&m);
pthread_cond_wait(&c, &m);
/* cond now true */

この 2 番目のスレッドは永久にブロックされます。これは、2 番目のスレッドで状態をチェックすることで回避されます。

pthread_mutex_lock(&m);
if (!cond)
    pthread_cond_wait(&c, &m);
/* cond now true */

condはミューテックスが保持された状態でのみ変更されるため、これはが false のm場合にのみ 2 番目のスレッドが待機することを意味します。cond

while ()堅牢なコードで の代わりにループが使用される理由は、誤って起動しないことを保証しないif ()ためです。pthread_cond_wait()a を使用するwhile ()ことは、条件変数のシグナル伝達が常に完全に安全であることも意味します。「余分な」シグナルはプログラムの正確性に影響を与えません。つまり、コードのロックされたセクションの外にシグナルを移動するなどのことができます。

于 2012-10-29T14:04:39.080 に答える