C语言线程对象和线程存储的实现
当每个线程为各自的变量使用全局标识符时,为保留这些变量各自的数据,可以采用线程对象(thread-localobject)和线程存储(thread-specificstorage)。
这两项技术允许在一个给定线程中执行的函数可以共享数据而不造成冲突,即便当其他线程也在执行同样函数的情况下。
使用线程对象
线程对象是在声明中包含新存储类修饰符_Thread_local的全局或静态对象。这意味着:每一个线程拥有属于自己的线程对象实例,它在线程启动时创建并初始化。对象的存储周期等于线程的运行时间。在一个线程内表达式里面的线程对象名,将引用这个对象在当前线程下的本地实例。
修饰符_Thread_local可以与修饰符static或extern同时使用。头文件threads.h定义了thread_local作为_Thread_local的同义词。在例1中,主线程和新启动线程各自拥有线程本地变量var的一个实例。
【例1】使用一个线程对象
#include#include thread_localintvar=10; voidprint_var(void){printf("var=%d\n",var);} intfunc(void*);//线程函数 intmain(intargc,char*argv[]) { thrd_tth1; if(thrd_create(&th1,func,NULL)!=thrd_success){ fprintf(stderr,"Errorcreatingthread.\n");return0xff; } print_var();//输出:var=10 thrd_join(th1,NULL); return0; } intfunc(void*arg)//线程函数 { var+=10;//线程本地变量 print_var();//输出:var=20 return0 }
使用线程存储
线程存储技术要比线程对象更加灵活。例如,独立线程可以使用不同大小的内存。它们可以动态地分配内存,并通过调用析构函数再次释放内存。同时,可以使用相同的标识符访问这些独立线程所在的不同内存区域。
这种灵活性通过初始创建一个全局的键(key)实现,该键表示了一个指向线程存储的指针。然后,独立线程通过指定其线程存储的位置加载这个指针。该全局键值是类型为tss_t的对象。头文件threads.h包含了该类型的定义以及4个用于管理线程存储(简称TSS)函数的声明:
inttss_create(tss_t*key,tss_dtor_tdtor);
通过析构函数dtor生成一个新的TSS指针,并且将key引用的对象设置为唯一标识该TSS指针的值。类型tss_dtor_t是一个函数指针,定义为void(*)(void*)(它指的是一个函数指针,该函数参数为void指针,并且该函数没有返回值)。dtor的返回值可以是一个空指针。
voidtss_delete(tss_tkey);
释放TSS键key所使用的所有资源。
inttss_set(tss_tkey,void*val);
对于调用tss_set()的线程,将key所标识的TSS指针设置为val所引用的内存地址。
void*tss_get(tss_tkey);
返回指向内存块的指针,该内存块为正在调用的线程通过函数tss_set()设置。如果发生错误,tss_get()返回NULL。
如果函数tss_create()和tss_set()发生错误,则返回thrd_error;否则,返回thrd_success。
例2中的程序在动态分配的线程存储中,保留线程的名称。
【例2】使用线程存储
#include#include #include #include tss_tkey;//用于TSS指针的全局键 intthFunc(void*arg);//线程函数 voiddestructor(void*data);//析构函数 intmain(void) { thrd_tth1,th2; intresult1=0,result2=0; //创建一个TSS密钥 if(tss_create(&key,destructor)!=thrd_success) return-1; //创建线程 if(thrd_create(&th1,thFunc,"Thread_1")!=thrd_success ||thrd_create(&th2,thFunc,"Thread_2")!=thrd_success) return-2; thrd_join(th1,&result1);thrd_join(th2,&result2); if(result1!=0||result2!=0) fputs("Threaderror\n",stderr); else puts("Threadsfinishedwithouterror."); tss_delete(key);//释放TSS指针所有的资源 return0; } voidprint(void)//显示线程存储 { printf("print:%s\n",(char*)tss_get(key)); } intthFunc(void*arg) { char*name=(char*)arg; size_tsize=strlen(name)+1; //设置线程存储 if(tss_set(key,malloc(size))!=thrd_success) return-1; //存储数据 strcpy((char*)tss_get(key),name); print(); return0; } voiddestructor(void*data) { printf("Destructorfor%s\n",(char*)data); free(data);//释放内存 }
到此这篇关于C语言线程对象和线程存储的实现的文章就介绍到这了,更多相关C语言线程对象和线程存储内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!