条件変数プログラムは2つのスレッドでは機能しますが、3つのスレッドでは機能しません

絶望的な放浪者

したがって、変数を0から100にインクリメントする2つのスレッドを持つこのプログラムがあり、正常に動作します。

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

int contor;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

void *incrementare(void *args) {
    int id = (int)args;
    while(1) {
        pthread_mutex_lock(&mutex);
        if (contor >= 100) {
            pthread_cond_signal(&cond);
            pthread_mutex_unlock(&mutex);
            pthread_exit(NULL);
        }

        while (contor %2 == id) {
        pthread_cond_wait(&cond,&mutex);
        }

        contor++;
        printf("Thread %d increment: %d\n",id,contor);


        pthread_cond_signal(&cond);
        pthread_mutex_unlock(&mutex);
    }
}

int main(void) {
    pthread_t th1, th2,th3;

    if(pthread_create(&th1, NULL, &incrementare, (void *)0) < 0) {
        perror("Error!\n");
        exit(1);
    }
    if(pthread_create(&th2, NULL, &incrementare, (void *)1) < 0) {
        perror("Error!\n");
        exit(2);
    }


    pthread_join(th1, NULL);
    pthread_join(th2, NULL);

    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);

    return 0;
}

結果は次のようになります。

Thread 1 increment: 1
Thread 0 increment: 2
Thread 1 increment: 3
Thread 0 increment: 4
Thread 1 increment: 5
Thread 0 incre.. and so on ,which is nice.

しかし、問題は3つのスレッドで試してみると、ランダムに発生するため機能しなくなります。変更を3回だけ行ったのですが、何が問題なのかわかりません。

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

int contor;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

void *incrementare(void *args) {
    int id = (int)args;
    while(1) {
        pthread_mutex_lock(&mutex);
        if (contor >= 100) {
            pthread_cond_signal(&cond);
            pthread_mutex_unlock(&mutex);
            pthread_exit(NULL);
        }

        while (contor %3 == id) {
        pthread_cond_wait(&cond,&mutex);
        }

        contor++;
        printf("Thread %d increment: %d\n",id,contor);


        pthread_cond_signal(&cond);
        pthread_mutex_unlock(&mutex);
    }
}

int main(void) {
    pthread_t th1, th2,th3;

    if(pthread_create(&th1, NULL, &incrementare, (void *)0) < 0) {
        perror("Error!\n");
        exit(1);
    }
    if(pthread_create(&th2, NULL, &incrementare, (void *)1) < 0) {
        perror("Error!\n");
        exit(2);
    }
    if(pthread_create(&th3, NULL, &incrementare, (void *)2) < 0) {
        perror("Error!\n");
        exit(3);
    }



    pthread_join(th1, NULL);
    pthread_join(th2, NULL);
        pthread_join(th3, NULL);


    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);

    return 0;
}

それは同じ権利をするべきですか?今は3つだけ。なぜ機能しないのですか?これがその仕組みです

Thread 2 increment: 1
Thread 2 increment: 2
Thread 1 increment: 3
Thread 1 increment: 4
Thread 2 increment: 5
Thread 1 increment: 6
WhozCraig

スレッドにサイクルを保証させたい場合は、N(スレッド数)を法とするカウンターが特定のIDになるまでその特定のID以外になるまで、スレッドを待機させる必要がありますIDが2つある場合、1つでなければ、もう1つでなければなりません。しかし、3つある場合、2つのケースが壊れ、1つのケースが待機します。スケジューラーは、解放したい2つのスペアスレッドのどちらかを自由に選択できます。

しかし、これを変更すると:

while (contor %3 == id)

これに:

while (contor %3 != id)

指定されたスレッドがそのIDを法とする値のみを書き込むように強制します

ただし、これだけでは不十分です。また、すべてのウェイターを起こす必要があります。以前は、スレッドが2つしかない場合、常に同じウェイターがいました。アクティブなスレッドではない「他の人」です。これはpthread_cond_signal特定のターゲットスレッド(実行されていない唯一のスレッド)に送信され、当然、次のスレッドでもあります。

スレッドが3つ以上ある場合、によって起動される可能性のある単一のスレッドpthread_cond_signalが、Nidを法とするcontorを持つスレッドではない可能性があります。実際、スレッドが多いほど、これが発生する可能性が高くなります。その場合、スレッドは待機状態に戻りますが、待機中の他のユーザーは再び起動されません。これを偶然に任せたくはありません。次のウェイターが信号を受信することを確認するために、すべてのウェイターが起こされていることを確認ください

別の場所に送信するだけでこれに対処ないでくださいpthread_cond_signal代わりに、代わりにブロードキャストを送信します。これを変更します。

pthread_cond_signal(&cond);

これに:

pthread_cond_broadcast(&cond);

これによりアクティブに待機しているすべてのスレッドが最終的に見た目に亀裂を生じ、Nを法としてcontor一致contorするスレッドは、バンプ、印刷、次のブロードキャストの送信、および待機に戻る機会を確実に得ることができます。

したがって、コードへの最小限の変更は次のようになります。

#include<stdio.h>
#include<stdlib.h>
#include<stdint.h>      // added for intptr_t
#include<inttypes.h>    // added for printf formatter for intptr_t
#include<pthread.h>

int contor;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

void *incrementare(void *args) {
    intptr_t id = (intptr_t)args; // proper way to pass an integer via thread param
    while(1) {
        pthread_mutex_lock(&mutex);
        if (contor >= 100) {
            pthread_cond_broadcast(&cond);
            pthread_mutex_unlock(&mutex);
            pthread_exit(NULL);
        }

        while (contor %3 != id) {
        pthread_cond_wait(&cond,&mutex);
        }

        contor++;
        printf("Thread %"PRIdPTR " increment: %d\n",id,contor);


        pthread_cond_broadcast(&cond);
        pthread_mutex_unlock(&mutex);
    }
    return NULL; // should always have well-defined return value
}

int main(void) {
    pthread_t th1, th2,th3;

    if(pthread_create(&th1, NULL, &incrementare, (void *)0) < 0) {
        perror("Error!\n");
        exit(1);
    }
    if(pthread_create(&th2, NULL, &incrementare, (void *)1) < 0) {
        perror("Error!\n");
        exit(2);
    }
    if(pthread_create(&th3, NULL, &incrementare, (void *)2) < 0) {
        perror("Error!\n");
        exit(3);
    }

    pthread_join(th1, NULL);
    pthread_join(th2, NULL);
    pthread_join(th3, NULL);

    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);

    return 0;
}

結果は以下のとおりです。

Thread 0 increment: 1
Thread 1 increment: 2
Thread 2 increment: 3
Thread 0 increment: 4
Thread 1 increment: 5
Thread 2 increment: 6
Thread 0 increment: 7
Thread 1 increment: 8
Thread 2 increment: 9
Thread 0 increment: 10
....
Thread 0 increment: 97
Thread 1 increment: 98
Thread 2 increment: 99
Thread 0 increment: 100
Thread 1 increment: 101
Thread 2 increment: 102

ライブで見る

余分な2つの出力は、ceiling-break条件をチェックするコードがcvar-predicateループの前にあるためです。それはなければなりませんが、私はあなたが対処するためにそれを残します。

ただし、これを行うと、タスクで複数のスレッドを緩めるという目的が最終的に無効になることに注意してください。理想的には、あなたが欲しいどんな実際にそうするように作業を実行するためにスレッドが利用できます。作業が単一のグローバルにのみ影響するということは、スレッド化の本当の目的をいくらか無効にします(明らかに、スレッド化を使用して100までカウントすることはありません。ループ内の単一のスレッドは、そのために理想的です)。


とにかく、プログラムの要約版が以下に表示されます。値を変更N_THREADSし、N_COUNT出力の違いを見るために。

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
#include <pthread.h>

#define N_THREADS 7
#define N_COUNT   100

int contor;  // 0

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

void *incrementare(void *args)
{
    intptr_t id = (intptr_t)args;
    pthread_mutex_lock(&mutex);
    while(1)
    {
        while (contor < N_COUNT && contor % N_THREADS != id)
            pthread_cond_wait(&cond, &mutex);

        if (contor == N_COUNT)
            break;

        printf("Thread %"PRIdPTR" increment: %d\n", id, ++contor);
        pthread_cond_broadcast(&cond);
    }
    pthread_mutex_unlock(&mutex);
    return NULL;
}

int main(void)
{
    pthread_t ar[N_THREADS];
    intptr_t id = 0;

    for (int i=0; i<N_THREADS; ++i)
    {
        if(pthread_create(ar+i, NULL, &incrementare, (void *)id++) < 0) {
            perror("Error!\n");
            exit(1);
        }
    }

    for (int i=0; i<N_THREADS; ++i)
        pthread_join(ar[i], NULL);

    return 0;
}

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

条件付きフォーマットルールは、Googleスプレッドシートでは機能しません。3番目を追加すると2つの条件で動作しますが動作しません

分類Dev

Visual C ++では1つのスレッドしか機能しません(OpenMP)

分類Dev

プログラムでの印刷は機能しますが、gdbは「アドレスのメモリにアクセスできません...」と表示します。

分類Dev

Unity-クラスの1つのメソッドは他のクラスでは機能しませんが、他のクラスでは機能します

分類Dev

sigwait()はマルチスレッドプログラムでは機能しません

分類Dev

Destructuring(スプレッド演算子)はReact JSXで機能しますが、外部では機能しませんか?

分類Dev

マルチスレッドプログラムはCでどのように機能しますか?

分類Dev

ブラウザのアクションはヘッドレスクロームでは機能しません

分類Dev

ドラッグアンドドロップはヘッドレスクロームドライバーでは機能しません

分類Dev

AWS S3アップロードはシミュレーターでは機能しますが、デバイスでは機能しません

分類Dev

Flaskでのスレッド化はUWSGIでは機能しませんが、コマンドラインで機能します

分類Dev

セレンを使用したstackoverflowへのログインは機能しますが、scrapy pythonの使用は機能しません。ヘッドレスブラウジングでログインするにはどうすればよいですか?

分類Dev

Ctrl + Shift + Enterキーを押して「管理者として実行」は「デスクトップアプリ」プログラムでは機能しますが、「コマンドの実行」プログラムでは機能しません

分類Dev

ディレクトリアップロードphpいくつかのdirsは機能しますが、いくつかは機能しません

分類Dev

C ++では、演算子のオーバーロードプレフィックスが機能しません

分類Dev

スクリプトは機能しますが、1つのスプレッドシートでのみ機能します

分類Dev

.batファイルは2つのドメインシステムで機能しますが、他のシステムでは機能しません

分類Dev

9つのパッチはXMLで機能しますが、コードでは機能しません

分類Dev

メソッドリファレンスはComparator.comparingメソッドで機能しますが、ラムダ式は機能しません

分類Dev

バックグラウンドスレッドは機能しませんが、単純な「System.out」では機能します

分類Dev

gretel gemを使用したブレッドクラムは、Herokuの開発環境では機能しますが、本番環境では機能しません。

分類Dev

高度なスロットリングは1つのサーバーでは機能しますが、他のサーバーでは機能しません

分類Dev

getRelevantGoogleReviewsはワードプレスの関数エラーではありませんが、ローカルホストで機能します

分類Dev

Googleスプレッドシート:カラースケールの条件付き書式は列Cでは機能しますが、列Bでは機能しません。修正に役立ちますか?

分類Dev

ホスト名付きのURLは機能しませんが、IPアドレスでは機能します

分類Dev

ドロワーはAppBarでのみ機能しますが、カスタムAppBarでは機能しません

分類Dev

Javaスレッドの中断は私には機能しません(Groovyで)

分類Dev

ドロップダウン付きの角型タンスレートはChromiumでは機能しません

分類Dev

Django:スラグのドットはDetailViewでは機能しません

Related 関連記事

  1. 1

    条件付きフォーマットルールは、Googleスプレッドシートでは機能しません。3番目を追加すると2つの条件で動作しますが動作しません

  2. 2

    Visual C ++では1つのスレッドしか機能しません(OpenMP)

  3. 3

    プログラムでの印刷は機能しますが、gdbは「アドレスのメモリにアクセスできません...」と表示します。

  4. 4

    Unity-クラスの1つのメソッドは他のクラスでは機能しませんが、他のクラスでは機能します

  5. 5

    sigwait()はマルチスレッドプログラムでは機能しません

  6. 6

    Destructuring(スプレッド演算子)はReact JSXで機能しますが、外部では機能しませんか?

  7. 7

    マルチスレッドプログラムはCでどのように機能しますか?

  8. 8

    ブラウザのアクションはヘッドレスクロームでは機能しません

  9. 9

    ドラッグアンドドロップはヘッドレスクロームドライバーでは機能しません

  10. 10

    AWS S3アップロードはシミュレーターでは機能しますが、デバイスでは機能しません

  11. 11

    Flaskでのスレッド化はUWSGIでは機能しませんが、コマンドラインで機能します

  12. 12

    セレンを使用したstackoverflowへのログインは機能しますが、scrapy pythonの使用は機能しません。ヘッドレスブラウジングでログインするにはどうすればよいですか?

  13. 13

    Ctrl + Shift + Enterキーを押して「管理者として実行」は「デスクトップアプリ」プログラムでは機能しますが、「コマンドの実行」プログラムでは機能しません

  14. 14

    ディレクトリアップロードphpいくつかのdirsは機能しますが、いくつかは機能しません

  15. 15

    C ++では、演算子のオーバーロードプレフィックスが機能しません

  16. 16

    スクリプトは機能しますが、1つのスプレッドシートでのみ機能します

  17. 17

    .batファイルは2つのドメインシステムで機能しますが、他のシステムでは機能しません

  18. 18

    9つのパッチはXMLで機能しますが、コードでは機能しません

  19. 19

    メソッドリファレンスはComparator.comparingメソッドで機能しますが、ラムダ式は機能しません

  20. 20

    バックグラウンドスレッドは機能しませんが、単純な「System.out」では機能します

  21. 21

    gretel gemを使用したブレッドクラムは、Herokuの開発環境では機能しますが、本番環境では機能しません。

  22. 22

    高度なスロットリングは1つのサーバーでは機能しますが、他のサーバーでは機能しません

  23. 23

    getRelevantGoogleReviewsはワードプレスの関数エラーではありませんが、ローカルホストで機能します

  24. 24

    Googleスプレッドシート:カラースケールの条件付き書式は列Cでは機能しますが、列Bでは機能しません。修正に役立ちますか?

  25. 25

    ホスト名付きのURLは機能しませんが、IPアドレスでは機能します

  26. 26

    ドロワーはAppBarでのみ機能しますが、カスタムAppBarでは機能しません

  27. 27

    Javaスレッドの中断は私には機能しません(Groovyで)

  28. 28

    ドロップダウン付きの角型タンスレートはChromiumでは機能しません

  29. 29

    Django:スラグのドットはDetailViewでは機能しません

ホットタグ

アーカイブ