6

書いたプログラムを書いたのですが、思った通りに動作しません。threadトリガーfuncanotherThreadトリガーの2つのスレッドがありますanotherFunc。私がやりたかったのは、で値に達したときにcont、とを使用してトリガーされることです。奇妙なことに、コメントを外すとすべてが正常に機能します。私はスレッドに不慣れで、ここのチュートリアルに従っていました。彼らの例の行にコメントすると、それも壊れます。10funcanotherThreadpthread_cond_waitpthread_cond_signalsleep(1)sleep

sleep()私の質問は、電話なしでこれをどのように機能させることができるかということです。そして、私のコードで両方が後funcに到達した場合はどうなりますか?どうすればこれらを制御できますか?これは私のコードです:pthread_mutex_lockanotherFunc

#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でのスレッドとネットワークに関するいくつかの優れたリファレンスまたはコース/チュートリアルを知っていますか?チャットクライアントの作成について学びたいのですが、そのためのスレッドとネットワークについて知っておく必要があると聞きました。問題は、私が何を知らなければならないかわからないので、私が学んだことが大丈夫かどうかはかなりよくわからないということです。

どうもありがとう :)

4

4 に答える 4

9

必要な条件 (カウンターが 10 に達する) が既に発生しているかどうかを最初にテストせずに、anotherThread単純に呼び出します。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);

また、スレッドを結合可能にするためだけにスレッド属性を作成する必要はありません。これは、作成属性にヌル ポインターを使用する場合の既定の状況です。POSIX スレッドは、デタッチして作成するか、 でデタッチに変換しない限り、結合可能pthread_detachです。

別のこと: 可能な限り、pthread_cond_signalmutex ロックを保持している間は呼び出しを避けてください。間違っているわけではありませんが、スレッドをウェイクアップするために操作で実際に OS カーネルを呼び出す必要がある可能性があるため、無駄になる可能性があります。アプリケーションで共有データを操作するいくつかのマシン命令を保護しています)。

于 2012-04-16T18:36:11.050 に答える
2

あなたの実際の問題が何であるかわかりません(それが機能しない場合はどうなりますか?)。

大きな問題が1つあります。それは、偽のウェイクアップを処理しないことです。

たとえば、ブール変数を使用して、条件が本当に真であることを示す何かが必要です。

初期化:

signaled = false;

信号:

signaled = true;
pthread_cond_signal(&cond);

受け取る:

while (!signaled)
   pthread_cond_wait(&cond, &myMutex);
于 2012-04-16T18:38:49.393 に答える
1

必要なのは、条件変数ではなくセマフォです。

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

簡単な実装については、こちらをご覧ください。

于 2012-04-16T18:55:52.163 に答える
0

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

これは単に別の代替手段です。

于 2012-04-16T18:52:09.257 に答える