サンプルコードに出会いました。
assume_order_of_execution_pitfall.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#define N 4
void* hello(void* arg)
{
printf("Hello World from Thread%d\n", *(int*)arg);
return NULL;
}
int main()
{
pthread_t tid[N];
int i;
for(i = 0; i < N; i++)
{
pthread_create(&tid[i], NULL, hello, (void*)&i); //&i points to same address
}
for(i = 0; i < N; i++)
{
pthread_join(tid[i], NULL);
}
return 0;
}
ここでは、スレッドが作成された瞬間に実行が開始されると誤って想定しています。printf() ステートメントは、pthread_create() への次の呼び出しの前に実際に実行される可能性がありますが、オペレーティング システムは任意の順序でスレッドを自由にスケジュールできます。いずれかのスレッドが実際に実行を開始する前に、すべてのスレッドが作成される可能性があります。のすべてのコピーがarg
同じアドレスを指しているため、 で変更されてmain()
いるため、スレッドは同じ を出力できますidentification number
。
using a unique address
以下に示すように、各スレッドの識別番号を保持することにより、上記のコードを修正しようとしました
assume_order_of_execution_workaround.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#define N 4
void* hello(void* arg)
{
printf("Hello World from Thread%d\n", *(int*)arg);
return NULL;
}
int main()
{
pthread_t tid[N];
int tno[N];
int i;
/* Added code */
for(i = 0; i < N; i++)
{
tno[i] = i + 1;
}/* Added code */
for(i = 0; i < N; i++)
{
pthread_create(&tid[i], NULL, hello, (void*)(tno+i)); // providing unique address for each thread
}
for(i = 0; i < N; i++)
{
pthread_join(tid[i], NULL);
}
return 0;
}
私の修正は正しい方法ですか?誰かが私にもっと正しい方法を提案できますか?