2012-04-16 1 views
6

私はプログラムを書いたと書いたが、私はそれが期待どおりに動作しません。 私は2つのスレッド:threadトリガーfuncanotherThreadトリガーanotherFuncを持っています。私がしたいのは、が10funcに達し、anotherThreadpthread_cond_waitpthread_cond_signalを使ってトリガされたときです。 sleep(1)行のコメントを外すと、奇妙なことはすべてうまくいきます。私はスレッドに新しく、私はチュートリアルhereに従っていましたが、もし私がsleepの行をコメントに書いていれば、それも壊れてしまいます。POSIX Cスレッド。 pthread_cond_tの例です。予期したとおりに動作しません

私の質問は、どのようにsleep()コールなしでこの仕事をすることができますか?私のコードでfuncがに達した場合はどうなりますか?anotherFuncの後にはどうなりますか?どうすればこれらのことをコントロールできますか?これは私のコードです:長い記事のため

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

pthread_mutex_t myMutex; 
pthread_cond_t cond; 
pthread_attr_t attr; 

int cont; 

void *func(void*) 
{ 
    printf("func\n"); 

    for(int i = 0; i < 20; i++) 
    { 
     pthread_mutex_lock(&myMutex); 

     cont++; 
     printf("%d\n", cont); 
     if(cont == 10) 
     { 
      printf("signal:\n"); 
      pthread_cond_signal(&cond); 
//   sleep(1); 
     } 
     pthread_mutex_unlock(&myMutex); 
    } 
    printf("Done func\n"); 

    pthread_exit(NULL); 
} 

void *anotherFunc(void*) 
{ 
    printf("anotherFunc\n"); 
    pthread_mutex_lock(&myMutex); 
    printf("waiting...\n"); 

    pthread_cond_wait(&cond, &myMutex); 
    cont += 10; 
    printf("slot\n"); 

    pthread_mutex_unlock(&myMutex); 
    printf("mutex unlocked anotherFunc\n"); 
    printf("Done anotherFunc\n"); 

    pthread_exit(NULL); 
} 

int main(int argc, char *argv[]) 
{ 
    pthread_t thread; 
    pthread_t anotherThread; 

    pthread_attr_init(&attr); 
    pthread_mutex_init(&myMutex, NULL); 
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 
    pthread_cond_init(&cond, NULL); 

    pthread_create(&anotherThread, &attr, anotherFunc, NULL); 
    pthread_create(&thread, &attr, func, NULL); 

    pthread_join(thread, NULL); 
    pthread_join(anotherThread, NULL); 

    printf("Done MAIN()"); 

    pthread_mutex_destroy(&myMutex); 
    pthread_cond_destroy(&cond); 
    pthread_attr_destroy(&attr); 


    pthread_exit(NULL); 
    return 0; 
} 

申し訳ありませんが、私はスレッドに新たなんだと私は学ぶために喜びました。また、Linux上のスレッドやネットワークに関するいくつかの良いリファレンスやコース/チュートリアルを知っていますか?私はチャットクライアントを作成することを学びたいと思うし、スレッドとネットワークを知る必要があると聞いた。問題は、私が知る必要があることが分からないので、私が学んだことが大丈夫だと、私はかなりよく分からない。

はそんなにありがとう:)

+0

その他の備考。私は 'pthread_attr_t'を使う必要がないことに加えて、コードを単純化するために条件とmutexに静的初期化子を使うことができます。さらに、あなたのスレッド関数は単に 'pthread_exit'を呼び出すのではなく' NULLを返します 'または' return 0; 'だけで済みます。そしてあなたのメインスレッドは、 'pthread_exit'を呼び出さずにmainから' return 0; 'だけすることができます。他のスレッドは、結合されてからその時点で実行されていません。 mainからの復帰はプロセスの終了を強制するが、プライマリスレッドの 'pthread_exit'はプロセス終了を強制しない。これは他のスレッドを実行させ続けるのに便利である。 – Kaz

+0

また、静的なミューテックスや条件をクリーンアップする必要はありません。 'pthread_mutex_t myMutex = PTHREAD_MUTEX_INITIALIZER;'を使うだけです。複雑な初期化は、通常とは異なる属性を設定する場合に必要です。例えば。プロセス共有の強力なミューテックスを作る。実行はpthread_cond_waitのに到達したとき、信号が受信されるまでスレッドがフリーズ: – Kaz

答えて

9

をごanotherThreadは、単に所望の条件(10に到達したカウンタ)がすでに起こっているかどうかを最初にテストを行わずにpthread_cond_waitを呼び出します。これは誤ったロジックです。ウェイクアップの問題が発生します:誤って書き込まれたマルチスレッドプログラムを悩ます反復バグの名前です。

条件変数はステートレスです。現在スレッドが待機していない状態でpthread_cond_signalまたはpthread_cond_broadcastが呼び出された場合、その操作は無効です。それは記憶されていません。したがって、シグナルスレッドが10に非常に素早くカウントし、他のスレッドがpthread_cond_waitコールに達する前に条件変数に信号を送ることが可能です。

周りにループが必要ですpthread_cond_wait。既に真である場合には条件をチェックしなければならないので、スレッドはすでに起きたウェイクアップを待たない。ウェイクアップは、スプリアスことができるので、それがループする必要があります:スレッドがpthread_cond_wait通って落下という理由だけ条件が実際に真であることを意味するものではありません:

while (cont < 10) 
    pthread_cond_wait(&cond, &myMutex); 

はまた、単にスレッド属性を作成する必要はありませんスレッドを結合可能にする。これは、作成属性にNULLポインタを使用する場合のデフォルトの状況です。 POSIXスレッドは、作成されたものがデタッチされていないか、またはpthread_detachでデタッチされていない限り結合可能です。

もう1つのこと:可能であれば、pthread_cond_signalにはミューテックスロックをかけたまま呼び出しないでください。間違っているわけではありませんが、実際にはOSカーネルを呼び出してスレッドを起動させなければならない可能性があり、システムコール全体にわたってこの高価なmutexロックを保持している可能性があります。アプリケーションの共有データを扱ういくつかの機械命令を保護しています)。

+0

あなたanotherThreadは、単に所望の条件(10に到達したカウンタ)は、すでに私は条件変数は次のように動作すると思っ が起こっているかどうかを最初にテストを行わずにpthread_cond_waitのを呼び出します。なぜ私は天気をテストしなければならないのですか?これは条件変数の仕事なので、すでに起こっていますか?なぜなら、私の条件に達したかどうかをテストするためのループを実行するだけで、このためのフラグを作成することができるからです。そのフラグが真のときには、もう一方のスレッドは終了します。 –

+0

私はあなたがコントロールすることができますどのように理解していないので、私は非常に困惑しているあなたが言ったように私はループ内でpthread_cond_waitのを入れてみましたが、それはまだ動作しません... http://pastebin.com/tNB9wCMW スレッドの実行がpthread_cond_signalの前にpthread_cond_waitに達する ありがとうございました –

+0

実行がpthread_cond_waitに達したときに実際に何が起こりますか。 信号が受信されるまでフリーズしますか?はいの場合、if文だけでなくwhileループが必要なのはなぜですか? –

2

実際の問題は何か分かりません(動作しないとどうなりますか)。

私は1つの大きな問題を参照してください、あなたはspurious wakeupsを処理しません。

のinit:

signaled = false; 

信号:

signaled = true; 
pthread_cond_signal(&cond); 

が受け取る:

while (!signaled) 
    pthread_cond_wait(&cond, &myMutex); 

あなたはブール変数と例えばその条件は本当に真の信号何かを、必要とします

+0

大きな問題は、* lost * wakeupです。このためには、 'pthread_cond_wait'の周りに' if'が必要です。偽の起床は軽微な問題であり、それは「中」である必要があります。このワンショットの状況では、ほんの2つのスレッドで偽のウェークアップが起きることはほとんどありません。 – Kaz

+0

yepp、私はあなたの優れた答えを見た;) –

0

これは単なるアイデアですが、セマフォを使用して "トリガー"を行うこともできます。私はずっと前に仕事をしていたプロジェクトを覚えています。私たちのスレッドの1つがトリガされるのを待っている間に(sem_waitを使って)ロックを取得しようと無限の時間を待っていただけですスケジューラによるprocと貴重なサイクルの節約)。メインスレッドが計算を終了すると、セマフォを解放して2番目のスレッドが計算を実行できるようにします。

これは単に別の方法です。何をしたい

1

はセマフォない条件変数です。

セマフォは、状態を維持し、カウントが待って()と信号()、それに対して。
通常、条件変数を使用して実装されます。

ささいな実装を探しhere

関連する問題