2012-01-21 20 views
2

スレッドの仕組みを理解しようとしています。私は学校からいくつかの例を持っています。このコードでは、なぜこのコードが適切に動作しないのかを理解する必要があります。その出力は次のとおりです。C言語のPOSIXスレッド

Main: Creating thread 0 
Main: Creating thread 1 
Main: Creating thread 2 
Main: Creating thread 3 
Main: Creating thread 4 
Main: Creating thread 5 
Main: Creating thread 6 
Main: Creating thread 7 
Main: Creating thread 8 
Thread 0: English: Hello World! 
Thread 0: English: Hello World! 
Thread 0: English: Hello World! 
Thread 0: English: Hello World! 
Thread 0: English: Hello World! 
Thread 0: English: Hello World! 
Thread 0: English: Hello World! 
Thread 0: English: Hello World! 
Thread 0: English: Hello World! 

しかし、すべてのスレッドは別の言語で 'Hello World'と言うべきです。ここに私のコードです。関数pthread_createの4番目のパラメータがポインタの代わりに(void *) tになったときに正常に動作します。しかし、私は正しいソリューションが(void *) &tであることを知っています。おそらく私はいくつかのポインタの問題を扱っていますが、私はちょうど

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

#define NUM_THREADS 8 

char *messages[NUM_THREADS + 1] = 
{ 
    "English: Hello World!", 
    "French: Bonjour, le monde!", 
    "Spanish: Hola al mundo", 
    "Klingon: Nuq neH!", 
    "German: Guten Tag, Welt!", 
    "Russian: Zdravstvytye, mir!", 
    "Japan: Sekai e konnichiwa!", 
    "Latin: Orbis, te saluto!", 
    "Cesky: Ahoj svete!" 
}; 


void * helloThread (void * threadid) 
{ 
    int *id_ptr, taskid; 

    sleep(1); 
    id_ptr = (int *) threadid; 
    taskid = *id_ptr; 
    printf("Thread %d: %s\n", taskid, messages[taskid]); 
    return(NULL); 
} 

int main(int argc, char *argv[]) 
{ 
    pthread_t threads[NUM_THREADS]; 
    int rc, t; 

    for(t=0;t<=NUM_THREADS;t++) { 
     printf("Main: Creating thread %d\n", t); 
     rc = pthread_create(&threads[t], NULL, helloThread, (void *) &t); 
     if (rc) { 
     printf("ERROR; return code from pthread_create() is %d\n", rc); 
     return (EXIT_FAILURE); 
     } 
    } 

    pthread_exit(NULL); 
    return (0); 
} 

答えて

1

あなたはmain()であなたのループイテレータtへのポインタを渡している...方法を見ることはできません。

ループがイテレーターの値を増やすと、実行中のスレッドはその時点のものを表示します。すべてのスレッドは何もする前に1秒間待つので、スレッドが完了するのを待たずにmain()から抜け出しているので、あなたが指しているものはもはや有効ではなく、あなたが見るものは未定義の動作になります。

5

間違っているいくつかのことがあります。

まずオフ、あなたが範囲を逸脱しています。ループはfor(t = 0; t < NUM_THREADS; t++)となります。

第二に、あなたは最後にこれを参加したり、プロセスを終了する前にスレッドを切り離し、そう言っている:

for(t = 0; t < NUM_THREADS; ++t) { 
    pthread_join(threads[t], NULL); 
} 

第三に、あなたはすべてのスレッドに同じポインタ(すなわち&t)を通過しています。これはあなたに間違った振る舞いを与えているだけでなく、競合状態やポインタの参照外しによって、未定義の動作にさらされています。代わりに、各スレッドに独自のメモリを与える:

int q[NUM_THREADS]; /* dedicated storage for each thread! */ 

for(t = 0; t < NUM_THREADS; ++t) { 
    printf("Main: Creating thread %d\n", t); 
    q[t] = t; 
    rc = pthread_create(threads + t, NULL, helloThread, q + t); 
    /* ... */ 
} 

(第四に、あなたはそれは不要だあなたは、メインスレッドを終了させるやり方でpthread_exitを呼び出すべきではありません、それは通常でmain()から戻るからあなたを排除します。

0

&tポインタを変数tにスレッドに渡します。すべてのスレッドは同じ変数(t)へのポインタを取得するので、各スレッドの値は任意の時点で同じになります。

シンプルなソリューション:

pthread_t threads[NUM_THREADS]; 
int thread_ids[NUM_THREADS]; // array which will hold the ID of each thread 
int rc, t; 

for(t=0;t<NUM_THREADS;t++) { // fixed 
    printf("Main: Creating thread %d\n", t); 
    thread_ids[t] = t; // setting the thread id 
    rc = pthread_create(&threads[t], NULL, helloThread, (void *) &thread_ids[t]); 
    // notice that I use &threads_ids[t] instead of &t 
    if (rc) { 
    printf("ERROR; return code from pthread_create() is %d\n", rc); 
    return (EXIT_FAILURE); 
    } 
}