Thread-specific data(TSD)线程私有数据

http://blog.chinaunix.net/uid-26885237-id-3209913.html

linux多线程编程中引入了Thread-Specific Data(线程相关的数据)的概念
为什么需要"线程相关的数据"呢?怎样使用"线程相关的数据"呢?
1. 为什么需要Thread-Specific Data "线程相关的数据"
这里只介绍我个人认为的一个原因, 当然它还有许多其他用途,欢迎大家讨论
例子:实现同时运行两个线程,对于每个线程,在该线程调用的每个函数中打印线程的名字,以及它正在调用的函数的名字.
(下面的例子与实现只是为了说明问题,有些地方可能不妥)
不使用"线程相关的数据"的两种实现方法:
实现方法1. 通过传参数,不使用全局变量
 
#include
#include
#define MAXLENGTH 20
void another_func (const char * threadName)
{
printf ("%s is running in another_func\n", threadName);
}
void * thread_func (void * args)
{
char threadName[MAXLENGTH];
strncpy (threadName, (char *)args, MAXLENGTH-1);
printf ("%s is running in thread_func\n", threadName);
another_func (threadName);
}
int main (int argc, char * argv[])
{
pthread_t pa, pb;
pthread_create ( &pa, NULL, thread_func, "Thread A");
pthread_create ( &pb, NULL, thread_func, "Thread B");
pthread_join (pa, NULL);
pthread_join (pb, NULL);
}
输出结果为:
Thread A is running in thread_func
Thread A is running in another_func
Thread B is running in thread_func
Thread B is running in another_func
该方法的缺点是:由于要记录是哪一个线程在调用函数,每个函数需要一个额外的参数来
记录线程的名字,例如another_func函数需要一个threadName参数
如果调用的函数多了,则每一个都需要一个这样的参数
实现方法2. 使用全局变量,通过互斥
 
#include
#include
#define MAXLENGTH 20
char threadName[MAXLENGTH];
pthread_mutex_t sharedMutex=PTHREAD_MUTEX_INITIALIZER;
void another_func ()
{
printf ("%s is running in another_func\n", threadName);
}
void * thread_func (void * args)
{
pthread_mutex_lock(&sharedMutex);
strncpy (threadName, (char *)args, MAXLENGTH-1);
printf ("%s is running in thread_func\n", threadName);
another_func ();
pthread_mutex_unlock(&sharedMutex);
}
int main (int argc, char * argv[])
{
pthread_t pa, pb;
pthread_create ( &pa, NULL, thread_func, "Thread A");
pthread_create ( &pb, NULL, thread_func, "Thread B");
pthread_join (pa, NULL);
pthread_join (pb, NULL);
}
该方法的缺点是:由于多个线程需要读写全局变量threadName,就需要使用互斥机制
分析以上两种实现方法,Thread-Specific Data "线程相关的数据"的一个好处就体现出来了:
(1)"线程相关的数据"可以是一个全局变量,并且
(2)每个线程存取的"线程相关的数据"是相互独立的.
 
2. 怎样使用"线程相关的数据"
这是利用"线程相关的数据"的实现方式:
 
#include
#include
pthread_key_t p_key;
void another_func ()
{
printf ("%s is running in another_func\n", (char *)pthread_getspecific(p_key));//绑定私有数据之后,就可以使用pthread_getspecific进行私有数据访问了
}
void * thread_func (void * args)
{
pthread_setspecific(p_key, args);//在各线程中将私有数据与关键字进行绑定
printf ("%s is running in thread_func\n", (char *)pthread_getspecific(p_key));//绑定私有数据之后,就可以使用pthread_getspecific进行私有数据访问了
another_func ();
}
int main (int argc, char * argv[])
{
pthread_t pa, pb;
pthread_key_create(&p_key, NULL);//在主线程中创建关键字
pthread_create ( &pa, NULL, thread_func, "Thread A");
pthread_create ( &pb, NULL, thread_func, "Thread B");
pthread_join (pa, NULL);
pthread_join (pb, NULL);
}
说明:
(1)
线程A, B共用了p_key,
通过p_key,就可以存取只跟当前线程相关的一个值(这个值由编译器管理)
线程A----->p_key----->线程A相关的值(由编译器管理)
线程B----->p_key----->线程B相关的值(由编译器管理)
设置"线程相关的数据",使用
int pthread_setspecific(pthread_key_t key, const void *pointer);
读取"线程相关的数据",使用
void * pthread_getspecific(pthread_key_t key);
注意到,这两个函数分别有一个void类型的指针,我们的线程就是通过这两个指针分别与
"线程相关的数据"的数据进行交互的
(2)
由于p_key是一个全局变量,
函数another_func不需要额外的参数就可以访问它;
又因为它是"线程相关的数据", 线程A, B通过p_key存取的数据是相互独立的,
这样就不需要额外的互斥机制来保证数据访问的正确性了

================== End

Thread-specific data(TSD)线程私有数据的更多相关文章

  1. 线程存储(Thread Specific Data)

    线程中特有的线程存储, Thread Specific Data .线程存储有什么用了?他是什么意思了? 大家都知道,在多线程程序中,所有线程共享程序中的变量.现在有一全局变量,所有线程都可以使用它, ...

  2. linux线程私有数据---TSD池

    进程内的所有线程共享进程的数据空间,所以全局变量为所有线程共有.在某些场景下,线程需要保存自己的私有数据,这时可以创建线程私有数据(Thread-specific Data)TSD来解决.在线程内部, ...

  3. 线程私有数据TSD——一键多值技术,线程同步中的互斥锁和条件变量

    一:线程私有数据: 线程是轻量级进程,进程在fork()之后,子进程不继承父进程的锁和警告,别的基本上都会继承,而vfork()与fork()不同的地方在于vfork()之后的进程会共享父进程的地址空 ...

  4. Posix线程编程指南(2) 线程私有数据

    概念及作用 在单线程程序中,我们经常要用到"全局变量"以实现多个函数间共享数据.在多线程环境下,由于数据空间是共享的,因此全局变量也为所有线程所共有.但有时应用程序设计中有必要提供 ...

  5. UNIX环境高级编程——线程私有数据

    线程私有数据(Thread-specific data,TSD):存储和查询与某个线程相关数据的一种机制. 在进程内的所有线程都共享相同的地址空间,即意味着任何声明为静态或外部变量,或在进程堆声明的变 ...

  6. pthread_getspecific()--读线程私有数据|pthread_setspecific()--写线程私有数据

    原型: #include <pthread.h> void *pthread_getspecific(pthread_key_t key); int pthread_setspecific ...

  7. linux多线程学习笔记六--一次性初始化和线程私有数据【转】

    转自:http://blog.csdn.net/kkxgx/article/details/7513278 版权声明:本文为博主原创文章,未经博主允许不得转载. 一,一次性初始化 以保证线程在调用资源 ...

  8. Linux系统编程——线程私有数据

    在多线程程序中.常常要用全局变量来实现多个函数间的数据共享.因为数据空间是共享的,因此全局变量也为全部线程共同拥有. 測试代码例如以下: #include <stdio.h> #inclu ...

  9. ZT linux 线程私有数据之 一键多值技术

    这个原作者的这个地方写错了 且他举的例子非常不好.最后有我的修正版本 pthread_setspecific(key, (void *)&my_errno); linux 线程私有数据之一键多 ...

随机推荐

  1. maven 发现有一个包 需要升级包版本

    maven有个包需要升级版本号,但是升级完了之后,怎么编译都是原来的: 后来修改了一下版本号,然后编译,就好了,再把版本号改回来就行了: 本地版本库地址:File==>Other Setting ...

  2. APP性能测试工具GT的使用总结:app内存测试

    APP性能测试工具GT的使用总结:app内存测试 GT(随身调)是APP的随身调测平台,它是直接运行在手机上的“集成调测环境”(IDTE, Integrated Debug Environment). ...

  3. SQLServer ROW_NUMBER()函数使用方法 分区排序

    #ROW_NUMBER() over()能干什么? 既可满足分区的需求,也可以根据一定的顺序来排序. #细细说 select ROW_NUMBER() over(partition by xm Ord ...

  4. Oralce 如何将查询结果中的0转成空的

    我们遇到过大多的情况的需求是查询结果中空转为0,这个可以通过oracle的NVL()函数就可以搞定. 之前做报表客户有个需求,查询出结果为0 要转成空的,不显示0 那么在oracle有没有现成函数能搞 ...

  5. windows server2012 R2安装python3.x版本报错0x80240017

    windows server2012 R2安装python3.x版本报错0x80240017 环境: windows server 2012 R2系统 问题: 安装python3.5版本时候出现错误0 ...

  6. (6)Flask项目之会员注册页面

    一.添加注册页面的路由 修改app/home/views.py内容,追加注册("/regist/")页面的路由: # coding:utf8 from . import home ...

  7. python问题集

    1.selenium.common.exceptions.WebDriverException: Message: 'chromedriver' executable needs to be in P ...

  8. 本地jar包上传docker容器

    先安装docker的注册服务器: [root@VM_0_7_centos ~]# docker run -d -p : --restart=always --name registry2 regist ...

  9. [python语法]python中如何判断一个集合是另一个集合的子集?

    问:python中如何判断一个集合是另一个集合的子集? 答:用issubset()方法 语法: A.issubset(B) 返回: True 如果A是B的子集. False 如果A不是B的子集. 样例 ...

  10. Pytorch 类别平衡化处理

    采用  WeightedRandomSampler: def make_weights_for_balanced_classes(images, nclasses): count = [0] * nc ...