5

マンページからpthread_key_create

オプションのデストラクタ関数を各キー値に関連付けることができます。スレッドの終了時に、キー値に NULL 以外のデストラクタ ポインタがあり、スレッドにキーに関連付けられた NULL 以外の値がある場合、ポイントされている関数は、現在関連付けられている値を唯一の引数として呼び出されます。スレッドの終了時に複数のデストラクタが存在する場合、デストラクタ呼び出しの順序は指定されていません。

関連するデストラクタを持つすべての非 NULL 値に対してすべてのデストラクタが呼び出された後、関連するデストラクタを持つ非 NULL 値がまだある場合は、プロセスが繰り返されます。未解決の非 NULL 値に対するデストラクタ呼び出しの少なくとも [PTHREAD_DESTRUCTOR_ITERATIONS] 回の反復の後、関連付けられたデストラクタにまだいくつかの非 NULL 値がある場合、実装はデストラクタの呼び出しを停止します。

NULL 以外のスレッド固有の値に対して "Hello World" を出力する単純なデストラクタを使用した小さな例を書きました。私が見る限り、このデストラクタは、デストラクタへの最初の呼び出しの後、スレッド固有の値がまだ NULL ではない場合でも、(少なくとも Linux の fedora と mac os x では) 1 回だけ呼び出されます。

私は何かを逃しましたか?(glibc では PTHREAD_DESTRUCTOR_ITERATIONS = 4)。

ここに私の小さな例があります:

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

#define NB_THREADS 1
#define NB_KEYS 1

static pthread_key_t keys[NB_KEYS];
static pthread_mutex_t mutex;

void destruction (void *arg)
{
  (int) arg ++;
  printf ("Destructor called! -- key value : %i\n", (int)arg);
}

void* startup_routine(void* argv)
{
  int i;
  int th = (int) argv;

  for (i = 0; i < NB_KEYS; i++)
    pthread_setspecific(keys[i], (void*) ((th + i)* 2));

  pthread_mutex_lock(&mutex);

  printf("Thread %i\n", th);

  for (i = 0; i < NB_KEYS; i++)
    printf ("\tkeys[%i] : %i\n", i, (int)pthread_getspecific(keys[i]));

  pthread_mutex_unlock(&mutex);

  return "End";
}

int main(int argc, char** argv)
{
  int i;
  void *result;
  pthread_t thread[NB_THREADS];

  for (i = 0; i < NB_KEYS; i++)
    pthread_key_create(&keys[i], destruction);

  pthread_mutex_init(&mutex, NULL);

  for (i = 0; i < NB_THREADS; i++)
    pthread_create( &thread[i], NULL, startup_routine, (void*)(i+1) );

  for (i = 0; i < NB_THREADS; i++)
  {
    pthread_join( thread[i], &result );
    printf("Return from the thread %i = '%s'\n", i, (char*)result );
  }

  return 0;
}
4

2 に答える 2

4

ここではpthreadを使用している人はあまりいないようです。

だから、もう一度、私は自分の質問に答えます:

pthread_setspecificキーの値を変更してデストラクタで呼び出しが行われた場合にのみ、デストラクタが複数回呼び出されます。

これは、デストラクタを呼び出す前に、キーポインタがnullに設定され、ポインタがデストラクタに渡されるためです。したがって、キーポインタをnullにしないようにする場合は、その中でリコールpthread_setspecificする必要があります。

于 2009-02-23T14:00:33.647 に答える
-1

謎がわかりません。スレッド固有のキーは 1 つだけで、スレッド固有のデータを設定するスレッドは 1 つだけです。したがって、デストラクタは期待どおり 1 回だけ実行する必要があります。

main() の pthread_create() の後のどこかにスレッド固有のデータを設定すると、デストラクタが 2 回呼び出されます。1 回は子スレッド用で、もう 1 回は main() に関連付けられたスレッド用です。

于 2010-01-14T09:02:02.957 に答える