2017-02-16 9 views
0

ここに私が書いた簡単なプログラムがあります。これは、ループの中に10個のスレッドを作成し、各スレッドは、iの値を出力します。Pthreadが正しい値を出力しない

#include <stdio.h> 
#include <pthread.h> 
void* basic_function(void *num){ 
    int cur_num = *(int*)num; 
    printf("Current thread number is :%d\n", cur_num); 
    return NULL; 
} 

int main(int argc, const char * argv[]) { 
    pthread_t thread_id [10]; 
    void * exit_status[10]; 

    for (int i = 0; i < 10; i++){ 
     pthread_create(&thread_id[i], NULL, basic_function, &i); 
     printf("i is: %d\n", i); 
    } 


    for (int i = 0; i<10; i++){ 
     pthread_join(thread_id[i], &exit_status[i]); 


    return 0; 
} 

私は出力が正しい順序で、0から9まで、いくつかのprint文のようになるはずだと思う:

Current thread number is: 0 
i is: 0 
Current thread number is: 1 
i is: 1 
Current thread number is: 2 
i is: 2 
... 

しかし、その代わりに、私の出力は次のとおりです。

i is: 0 
i is: 1 
i is: 2 
i is: 3 
i is: 4 
i is: 5 
Current thread number is: 6 
Current thread number is: 6 
i is: 6 
Current thread number is: 6 
Current thread number is: 6 
Current thread number is: 6 
Current thread number is: 6 
Current thread number is: 6 
i is: 7 
Current thread number is: 7 
i is: 8 
Current thread number is: 9 
Current thread number is: 9 
i is: 9 

スレッド6が複数回作成されたのはなぜ?なぜいくつかのスレッドは作成されませんか?また、プログラムを実行すると、なぜ私はいつも異なる出力を得るのですか?

答えて

1

スレッド関数に渡される引数が同じ変数 - iを指しているためです。

、変数iが常にmain機能から更新されたとして、スレッドは常に自分の走行時の最新の値を取得し、スレッドがmain方法と並行して、それを行います。さらに、ループがすでに終了している場合にスレッドが変数にアクセスし、そのような場合には未定義の動作が発生することがあります。

解決策は、iのコピーをヒープに割り当てて、そのコピーにポインタを渡すことです。あるいは、少し汚れた解決策は、iをポインタにキャストし、引数として渡してから、スレッドに変換してintに戻すことです。これはポインタよりもintが小さいことに頼っていますが、これはかなり一般的ですが、あまりにも曖昧なアーキテクチャではそうではないかもしれません。

+0

私はあなたの最初の解決策を理解しています。しかし、なぜ私はポインタにキャストして問題を解決できるのか分かりません。私はそれが 'pthread_create(&thread_id [i]、NULL、basic_function、&i)'と同じ効果を持っていると思います。 – HalfOfRain

+0

いいえ、ポインタにキャストすると、ポインタによって運ばれる整数のコピーが作成されるため、同じ効果はありません。 Zbynekが指摘しているようにポータブルではありませんが、動作すれば信頼性があります – LWimsey

関連する問題