4

I'm working through some simple pthread examples form llnl.computing.gov pthreads tutorial. The program on the website prints out the address of the threadid, but I would like to pass the address of the id to PrintHello, and then use dereference the address to get the id. I think with the sleep in there every thread should print 8 (the number of threads). The code is

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define NUM_THREADS  8

void *PrintHello(void *threadid)
{
   long *taskid = (long *)threadid;
   sleep(1);
   printf("Hello from thread %ld\n", *taskid);
   pthread_exit(NULL);
} 

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

  for(t=0;t<NUM_THREADS;t++) {
    printf("Creating thread %ld\n", t);
    rc = pthread_create(&threads[t], NULL, PrintHello, (void *) &t);
    if (rc) {
      printf("ERROR; return code from pthread_create() is %d\n", rc);
      exit(-1);
    }
 }
 pthread_exit(NULL);
}

When I compile and run this in Cygwin it seg faults with stack corruption errors. If I rewrite PrintHello as:

void *PrintHello(void *threadid)
{
  long taskid = (long) threadid;
  sleep(1);
  printf("Hello from thread %ld\n", taskid);
  pthread_exit(NULL);
 }

it doesn't seg fault, it just prints the address and I would like to dereference the address and get the value of t from main.

Does anyone have some pointers on how to accomplish that goal? I know I can pass t to pthread_create instead of &t but I want to do it this way for learning purposes.

4

3 に答える 3

9

メインスレッドから呼び出すとpthread_exit(NULL)、そのスレッドは終了します。その時点でmain、を含む関数内のローカル変数tは破棄され、使用できなくなります。

すべてのワーカースレッドの使用が終了する前にt(を介してそれらに渡すポインターを介してpthread_create)メインスレッドが終了すると、プログラムは未定義の動作を示します。

tワーカースレッドからの変数へのアクセスとtメインスレッドからの変数の破棄が非同期であるため、プログラムには競合状態が含まれています。この問題を解決する1つの方法は、メインスレッドをpthread_join終了する前に各ワーカースレッドと(を介して)結合させることです。

于 2012-08-09T20:36:32.103 に答える
4

1)のアドレスを渡すと、tすべてのスレッドが同じ変数へのポインターを取得します。これはスレッドIDではなくlong、値が変化し続けるaです。変数を変更し、main他のスレッドで読み取ります。これはデータの競合です。

2)おそらく何が起こるかというと、新しいスレッドがループを実行するまでにループインmainが終了し、変数がスコープ外になっていることです。終了するmainと、そのローカル変数はスタックからポップされます。そのため、他のスレッドがアクセスtすると、そのローカル変数はスタック上になくなります。これを防ぐための同期がプログラムにないため、別のデータ競合が発生します。スレッドが終了するのを待つ必要があります。これは、各スレッドを待機mainするように呼び出すことで実行できますpthread_joinが、それでも、他のスレッドが別のスレッドによって書き込まれているときに他のスレッドが変数を読み取ろうとしているという事実は変わりません。

3)そこで呼び出す必要はありませんpthread_exit。関数またはメインから戻ると、スレッドが自動的に終了します(呼び出しexit(0)main()終了するのと同じように)

于 2012-08-09T20:37:10.507 に答える
0

いくつかのポインタ?まあ、スレッド関数にはたくさんあります...

問題: ローカル変数のアドレスを安全に渡すことができません。メインが終了するとスコープ外になります。ポインタを静的グローバル変数として宣言するか、malloc() sizeof(long) バイトのメモリを使用してそれを使用する必要があります。

于 2012-08-09T20:39:06.653 に答える