我正在学习POSIX线程,我已经开始讨论线程特定数据。本书使用文件描述符做了一个很好的例子。但是,我想自己做同样的例子,除了这次使用全局变量。但是,我在完全理解这个概念时遇到了一些困难。
我想做的是以下内容:
在main中:
在thread_func中:
以下是代码:
#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时,每个线程应该有自己唯一的内存地址的内存地址 - 我在这里没有发现这种情况。我知道我没有正确地解决这个问题,当我在做特定操作时尝试查看每个线程的内存地址时,我看到了相同的内存地址。也许有人可以指出我使用全局变量(不是文件描述符)的示例,并且它们具有特定于线程的用法,其中线程将其视为局部变量。
答案 0 :(得分:18)
这不是答案,而是旁注:
如果您正在使用特定于Linux的代码,则可以使用__thread
关键字。从本质上讲,
static __thread int counter = 5;
为每个线程创建一个不同的counter
变量,每当创建一个新线程时,该变量初始化为值5。此类代码与C11未来兼容,因为C11使用_Thread_local
关键字标准化了相同的语义。这比使用C的所有体系结构上的POSIX线程专用函数(具有特定于实现的限制,并且与__thread
关键字相比非常麻烦)更加安全,除了那些已声明C99及更高版本的< em>标准不受欢迎“(即微软)。
有关详细信息,请参阅Thread-Local Storage chapter中的GCC documentation。
答案 1 :(得分:15)
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
答案 2 :(得分:4)
一般来说,您正在寻找的是“线程本地存储”。以下是一些链接:
选择pthread_getspecific()
是正确的。这是一个很好的例子:
请查看以上示例:我认为它会指出您的问题......或建议一个好的替代方案。
... IMHO