我如何使用POSIX线程创build一个全局variables,它是C中的线程特定的?

我正在学习有关POSIX线程,我已经到了线程特定数据部分。 本书使用文件描述符做了一个很好的例子。 但是,我想自己做同样的例子,除了这次使用全局variables。 但是,我完全理解这个概念有些困难。

我想要做的是以下几点:

  • 创build一个全局整数
  • 为全局int声明一个键

主要:

  • 设置全局整数是一个值例如。 10
  • 为它创build一个关键没有任何清理
  • 创build4个线程并发送它们来执行thread_func
  • 检查值是否仍然是10,因为线程只能看到它的副本

在thread_func中:

  • 使用pthread_setspecific(键,全局variables)创build一个本地实例 – 不知道我是否正确解释
  • 调用函数 – dosomething()
  • 出口

在do_something中

  • 创build一个本地指针,并将其分配给pthread_getspecific(key) – 这应该让我一个线程特定版本的全局variables
  • 将存储在本地指针的值更改为2
  • 出口

代码如下:

#include <pthread.h> #include <stdio.h> #include <stdlib.h> #define NUMTHREADS 4 pthread_key_t glob_var_key; int glob_var; void do_something() { //get thread specific data int* glob_spec_var = (int*) pthread_getspecific(glob_var_key); printf("Thread %d glob_spec before mod value is %d\n", (unsigned int) pthread_self(), *glob_spec_var); *glob_spec_var = 2; printf("Thread %d glob_spec after mod value is %d\n", (unsigned int) pthread_self(), *glob_spec_var); } void* thread_func(void *arg) { pthread_setspecific(glob_var_key, &glob_var); do_something(); pthread_exit(NULL); } int main(void) { pthread_t threads[NUMTHREADS]; int i; glob_var = 10; pthread_key_create(&glob_var_key,NULL); printf("Main: glob_var is %d\n", glob_var); for (i=0; i < NUMTHREADS; i++) { pthread_create(&threads[i],NULL,thread_func,NULL); } for (i=0; i < NUMTHREADS; i++) { pthread_join(threads[i], NULL); } printf("Main: glob_var is %d\n", glob_var); return 0; } 

从我的理解,当你调用pthread_getspecific,每个线程应该有自己的内存地址的内存地址 – 我没有发现这里的情况下。 我知道我没有正确的解决这个问题,当我试图在每个线程的内存地址做特定的时候,我看到了相同的内存地址。 也许有人可以给我一个例子,他们使用全局variables(而不是文件描述符),他们有线程特定的用法,在这个用法中线程把它看作是一个局部variables。

TLS(线程本地存储)的目的是提供一个定义的机制,从而代码可以检索存储在由全线程已知共享密钥访问的数据库中的线程特定数据。 您的代码在TLS中存储相同的数据:单个全局变量的地址)。 因此,当一个线程使用tls-key请求这个数据时,它们将全部取回相同的地址。

我想你打算你的代码做这样的事情:

 #include <stdio.h> #include <stdlib.h> #include <pthread.h> #define NUMTHREADS 4 pthread_key_t glob_var_key; void do_something() { //get thread specific data int* glob_spec_var = pthread_getspecific(glob_var_key); printf("Thread %d before mod value is %d\n", (unsigned int) pthread_self(), *glob_spec_var); *glob_spec_var += 1; printf("Thread %d after mod value is %d\n", (unsigned int) pthread_self(), *glob_spec_var); } void* thread_func(void *arg) { int *p = malloc(sizeof(int)); *p = 1; pthread_setspecific(glob_var_key, p); do_something(); do_something(); pthread_setspecific(glob_var_key, NULL); free(p); pthread_exit(NULL); } int main(void) { pthread_t threads[NUMTHREADS]; int i; pthread_key_create(&glob_var_key,NULL); for (i=0; i < NUMTHREADS; i++) pthread_create(threads+i,NULL,thread_func,NULL); for (i=0; i < NUMTHREADS; i++) pthread_join(threads[i], NULL); return 0; } 

产量

 Thread 2625536 before mod value is 1 Thread 741376 before mod value is 1 Thread 3162112 before mod value is 1 Thread 3698688 before mod value is 1 Thread 2625536 after mod value is 2 Thread 741376 after mod value is 2 Thread 3162112 after mod value is 2 Thread 3698688 after mod value is 2 Thread 2625536 before mod value is 2 Thread 741376 before mod value is 2 Thread 3162112 before mod value is 2 Thread 3698688 before mod value is 2 Thread 2625536 after mod value is 3 Thread 741376 after mod value is 3 Thread 3162112 after mod value is 3 Thread 3698688 after mod value is 3 

这不是一个答案,而是一个附注:

如果您正在使用特定于Linux的代码,则可以使用__thread关键字。 从本质上讲,

 static __thread int counter = 5; 

为每个线程创建一个不同的counter变量,每当创建一个新线程时将其初始化为值5。 这样的代码将来与C11兼容,因为C11使用_Thread_local关键字标准化相同的语义。 除了那些已经声明C99和后来的“ 标准不受欢迎 ”的(除了__thread关键字之外),这比使用C的POSIX特定于线程的函数(具有实现特定的限制,并且相对于__thread关键字相当麻烦)要__thread即微软)。

有关详细信息,请参阅GCC文档中的“ 线程局部存储”一章 。

一般来说,你要找的是“线程本地存储”。 这里有几个链接:

选择pthread_getspecific()是正确的。 这是一个很好的例子:

请回顾一下上面的例子:我认为这会指出你的问题…或者建议一个好的选择。

恕我直言…