6

これは私の最初の pthread プログラムであり、printf ステートメントが子スレッドで 2 回出力される理由がわかりません。

int x = 1;

void *func(void *p)
{
    x = x + 1;
    printf("tid %ld: x is %d\n", pthread_self(), x);
    return NULL;
}

int main(void)
{
    pthread_t tid;
    pthread_create(&tid, NULL, func, NULL);

    printf("main thread: %ld\n", pthread_self());

    func(NULL);
}

私のプラットフォームで観察された出力 (Linux 3.2.0-32-generic #51-Ubuntu SMP x86_64 GNU/Linux):

1.
main thread: 140144423188224
tid 140144423188224: x is 2

2.
main thread: 140144423188224
tid 140144423188224: x is 3

3.
main thread: 139716926285568
tid 139716926285568: x is 2
tid 139716918028032: x is 3
tid 139716918028032: x is 3

4.
main thread: 139923881056000
tid 139923881056000: x is 3
tid 139923872798464tid 139923872798464: x is 2

3 の場合、子スレッドからの 2 つの出力行

4 の場合は 3 と同じで、出力もインターリーブされます。

4

3 に答える 3

2

本当の答えは、この glibc バグを参照する Michael Burr のコメントのようです: https://sourceware.org/bugzilla/show_bug.cgi?id=14697

要約すると、glibc はプログラムの終了時に stdio バッファーを正しく処理しません。

于 2015-10-16T17:31:36.733 に答える
2

スレッディングは、通常、時分割多重化によって発生します。一般に、プロセッサが 2 つのスレッド間で均等に切り替えることは非効率的です。これには、より多くの労力と高度なコンテキスト切り替えが必要になるためです。通常、スレッドは切り替え前に数回実行されます (例 3 と 4 の場合のように)。子スレッドは、最終的に終了する前に複数回実行されます (メイン スレッドが終了したため)。

例 2: 出力がないのに子スレッドによって x が増加する理由がわかりません。

このことを考慮。メインスレッドが実行されます。pthread を呼び出し、新しいスレッドが作成されます。新しい子スレッドは x をインクリメントします。子スレッドが printf ステートメントを完了する前に、メイン スレッドが開始されます。突然、x もインクリメントされます。ただし、メイン スレッドは printf ステートメントを実行することもできます。突然 x が 3 になりました。メイン スレッドが終了します (子 3 も終了します)。これは、例 2 の場合に発生した可能性があります。

例 3 は、非効率的なロックとスタック データの破損により、変数 x が破損していることを明確に示しています!!

スレッドとは何かの詳細については。

リンク 1 - スレッドに関する追加情報

リンク 2 - スレッドに関する追加情報

また、x のグローバル変数を使用しているため、この変数へのアクセスはスレッド間で共有されていることがわかります。これはまずい.. 同じ変数にアクセスするスレッドが競合状態を引き起こし、変数 x の同じレジスタで複数の読み書きが発生するため、非常にまずい。複数のスレッドが同時に同じ変数を変更しようとするのを防ぐために、変数が更新されている間、基本的にロックを作成するミューテックスが使用されるのはこのためです。Mutex ロックにより、 x は、あなたの場合のように散発的にではなく、順次更新されます。

Pthreads in General および Mutex ロックの例の詳細については、このリンクを参照してください。
Pthreads および Mutex 変数

乾杯、
ピーター

于 2012-11-25T12:08:04.527 に答える
2

うーん。あなたの例では、異なるスレッドから同じ「リソース」を使用しています。1 つのリソースは変数 x で、もう 1 つは標準出力ファイルです。したがって、ここに示すようにミューテックスを使用する必要があります。また、最後の pthread_join は、他のスレッドがそのジョブを完了するのを待ちます。(通常、これらすべての pthread... 呼び出しの戻りコードを確認することもお勧めします)

#include <pthread.h>
#include <stdio.h>
int x = 1;
pthread_mutex_t mutex;

void *func(void *p)
{
    pthread_mutex_lock (&mutex);
    x = x + 1;
    printf("tid %ld: x is %d\n", pthread_self(), x);
    pthread_mutex_unlock (&mutex);
    return NULL;
}

int main(void)
{
    pthread_mutex_init(&mutex, 0);

    pthread_t tid;
    pthread_create(&tid, NULL, func, NULL);

    pthread_mutex_lock (&mutex);
    printf("main thread:  %ld\n", pthread_self());
    pthread_mutex_unlock (&mutex);

    func(NULL);
    pthread_join (tid, 0);
}
于 2012-11-25T12:47:17.400 に答える