【问题标题】:C : pthread dataspecific destructor called only onceC : pthread 数据特定的析构函数只调用一次
【发布时间】:2010-10-09 07:03:06
【问题描述】:

来自pthread_key_create 手册页:

一个可选的析构函数可以 与每个键值相关联。在 线程退出,如果键值有 非 NULL 析构函数指针,以及 线程具有关联的非 NULL 值 用键,指向的函数 与当前关联的调用 价值作为其唯一的论据。这 析构函数调用的顺序是 如果多于一个,则未指定 当线程存在析构函数时 它退出了。

如果,毕竟所有的析构函数都有 为所有非 NULL 值调用 与相关的析构函数,有 仍然有一些非NULL值 关联的析构函数,然后 过程重复。如果,在之后 至少 [PTHREAD_DESTRUCTOR_ITERATIONS] 析构函数的迭代调用 杰出的非 NULL 值,有 仍然是一些非 NULL 值 相关的析构函数, 实现停止调用 析构函数。

我写了一个小例子,用一个简单的析构函数为非 NULL 线程特定值打印“Hello World”。据我所知,这个析构函数只被调用一次(至少在 linux fedora 和 mac os x 上),即使在第一次调用析构函数后线程特定的值仍然不是 NULL。

我错过了什么吗?! (在 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;
}

【问题讨论】:

    标签: c pthreads destructor


    【解决方案1】:

    看来这里用pthread的人不多啊!

    所以,我再次回答我自己的问题:

    仅当在析构函数中调用pthread_setspecific 时,才会多次调用析构函数,从而更改键的值。

    这是因为在调用析构函数之前,将键指针设置为null,并将指针传递给析构函数。所以如果我们希望键指针不为空,只需在其中调用pthread_setspecific即可。

    【讨论】:

    • 对。如果只有一个键值要析构,则析构函数只被调用一次。假设是析构函数实际上破坏了对象。析构函数可能被多次调用的原因是另一个析构函数的操作可能会重新创建值。
    【解决方案2】:

    我不明白其中的奥秘。您只有 1 个线程特定的键,并且只有 1 个设置线程特定数据的线程。因此析构函数应该只按预期执行一次。

    如果您在 main() 中的 pthread_create() 之后的某处设置线程特定的数据,则析构函数将被调用两次——一次用于子线程,一次用于与 main() 关联的线程。

    【讨论】:

    • 对于相同的线程特定数据,可能会多次调用析构函数!我只有一个线程这一事实并没有改变这一说法。
    • 关键是只有 1 个 set() 因此最多有 1 个析构函数调用。如果你有 2 个 sets(),最多会有 2 个析构函数调用。您最初的问题是“为什么只执行一次?”我告诉你为什么。它也与构造函数无关。如果在程序中调用 set() 10 次,它最多会调用析构函数 10 次。 opengroup.org/onlinepubs/000095399/functions/… 中的示例阐明了这一点。
    猜你喜欢
    • 2011-09-19
    • 2013-12-11
    • 2012-07-12
    • 2022-07-05
    • 1970-01-01
    • 1970-01-01
    • 2016-02-08
    • 2010-12-29
    相关资源
    最近更新 更多