锐英源软件
第一信赖

精通

英语

开源

擅长

开发

培训

胸怀四海 

第一信赖

当前位置:锐英源 / 开源技术 / 线程的特有数据
服务方向
人工智能数据处理
人工智能培训
kaldi数据准备
小语种语音识别
语音识别标注
语音识别系统
语音识别转文字
kaldi开发技术服务
软件开发
运动控制卡上位机
机械加工软件
软件开发培训
Java 安卓移动开发
VC++
C#软件
汇编和破解
驱动开发
联系方式
固话:0371-63888850
手机:138-0381-0136
Q Q:396806883
微信:ryysoft

线程的特有数据

有时在应用程序中使用的全局变量,我们希望它只作用于当前的线程。即我们希望每个子线程有针对它们自身的私有的全局变量,这个全局变量对别的线程不可见,这时就可以使用线程的特有数据(Thread specific data)。这个全局变量由当前线程分配空间,并加以保存。可以为这个全局变量分配一个销毁函数,当当前线程结束时,系统将会自动运行这个销毁函数,来清空当前线程分配的存储空间。我们可以使用线程的特有数据来代替全局变量,因为一个线程中,所有的函数对这片存储空间的请求,都会得到一个相同的值。而其它线程中的函数在相同的语句中访问的,是调用函数的线程自身的存储空间。(也就是线程与线程之间互不干扰)。

与线程的特有数据相关的函数为:
pthread_key_create()
pthread_setspecific()
pthread_getspecific()
pthread_key_delete()

在下面这个例子中,定义了一个pthread_key_t 结构的变量tlskey,这个变量虽然是全局变量,但在这个程序的使用中,实际上就是一个线程的特有数据,即它的作用空间仅限于当前线程。

首先,需要使用 pthread_key_create 命令来创建生成这个线程特有数据,同时为这个数据指定一个销毁函数globalDestructor。当子线程结束时,如果tlskey 自身,以及它所指向的数据都不为空的话, 那么系统将会自动运行销毁函数globalDestructor 。同时,pthread_key_create 函数在销毁函数参数不为空的时候,也就相当于将tlskey 指定成为的销毁函数的入口参数,所以在销毁函数中,直接对参数进行free()操作,其实也就是将tlskey 指向的地址空间释放,最后再把这片地址空间赋值为空。

在主线程中,每次创建子线程之前,都先分配一片存储空间,然后就这片空间的指针传递到子线程中;子线程通过pthread_setspecific 函数,将线程特有数据tlskey 指向了这片存储空间。于是,在当前线程中,所有的函数都可以共享这个特有数据tlskey,然后通过这个tlskey 再共享它所指向的存储空间。比如说showdata 函数,就是通过pthread_getspecific 函数使用了tlskey,从而访问到了存储空间中的数据。

当每个子线程结束的时候,系统将会自动运行销毁函数,打印出一句话,然后执行free操作,最后再使用pthread_setspecific 函数,将线程特有数据tlskey 指向的存储空间清空。

  #define _MULTI_THREADED
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define checkResults(string, val) { \
if (val) { \
printf("Failed with %d at %s", val, string); \
exit(1); \
} \
}
#define NUMTHREADS 3
pthread_key_t tlsKey = 0;
typedef struct {
int data1;
int data2;
} mystruct;
void globalDestructor(void *value)
{
printf("%.8x,%.8x: In the data destructor\n", \
pthread_getthreadid_np());
free(value);
pthread_setspecific(tlsKey, NULL);
}
void showdata()
{
mystruct *gdata;
gdata=pthread_getspecific(tlsKey);
printf("%.8x, %.8x: get data data1= %d, data2=%d\n", \
pthread_getthreadid_np(), gdata->data1, gdata->data2);
}
void *threadfunc(void *parm)
{
mystruct *gdata;
gdata=(mystruct *)parm;
printf("%.8x, %.8x: set data data1= %d, data2=%d\n", \
pthread_getthreadid_np(), gdata->data1, gdata->data2);
pthread_setspecific(tlsKey, gdata);
showdata();
printf("%.8x, %.8x: Ready exit thread, run function destruct\n",
pthread_getthreadid_np());
return NULL;
}
int main(int argc, char **argv)
{
pthread_t thread[NUMTHREADS];
int rc=0;
int i=0;
mystruct *gData;
printf("Enter Testcase - %s\n", argv[0]);
printf("Create a thread local storage key\n");
rc = pthread_key_create(&tlsKey, globalDestructor);
checkResults("pthread_key_create()\n", rc);
/* The key can now be used from all threads */
for(i=0;i<NUMTHREADS;i++){
gData=(mystruct *)malloc(sizeof(mystruct));
gData->data1=i;
gData->data2=(i+1)*i;
pthread_create(&thread[i], NULL, threadfunc, gData);
}
for(i=0;i<NUMTHREADS;i++)
pthread_join(thread[i], NULL);
printf("Delete a thread local storage key\n");
rc = pthread_key_delete(tlsKey);
checkResults("pthread_key_delete()\n", rc);
/* The key and any remaining values are now gone. */
printf("Main completed\n");
return 0;
}
友情链接
版权所有 Copyright(c)2004-2021 锐英源软件
公司注册号:410105000449586 豫ICP备08007559号 最佳分辨率 1024*768
地址:郑州大学北校区院(文化路97号院)内