博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Linux多线程实践(四 )线程的特定数据
阅读量:4700 次
发布时间:2019-06-09

本文共 3414 字,大约阅读时间需要 11 分钟。

在单线程程序中。我们常常要用到"全局变量"以实现多个函数间共享数据, 然而在多线程环境下。因为数据空间是共享的。因此全局变量也为全部线程所共同拥有。但有时应用程序设计中有必要提供线程私有的全局变量,仅在某个线程中有效,但却能够跨多个函数訪问。POSIX线程库通过维护一定的数据结构来解决问题。这个些数据称为(Thread-specific-data或 TSD)。

相关函数例如以下:

int pthread_key_create(pthread_key_t *key, void (*destr_function) (void *));  int pthread_key_delete(pthread_key_t key);    int pthread_setspecific(pthread_key_t key, const void *pointer);  void * pthread_getspecific(pthread_key_t key);    pthread_once_t once_control = PTHREAD_ONCE_INIT;  int pthread_once(pthread_once_t *once_control, void (*init_routine) (void));

  从上图可知:当调用pthread_key_create 后会产生一个全部线程都可见的线程特定数据(TSD)的键值(如上图中全部的线程都会得到一个pkey[1]的值), 可是这个键所指向的真实数据却是不同的,尽管都是pkey[1], 可是他们并非指向同一块内存,而是指向了仅仅属于自己的实际数据, 因此, 假设线程0更改了pkey[1]所指向的数据, 而并不可以影像到线程n;

   在线程调用pthread_setspecific后会将每一个线程的特定数据与thread_key_t绑定起来,尽管仅仅有一个pthread_key_t。但每一个线程的特定数据是独立的内存空间,当线程退出时会运行destructor 函数。

/** 演示样例1:运用pthread_once, 让key仅仅初始化一次 注意: 将对key的初始化放入到init_routine中 **/  pthread_key_t key;  pthread_once_t once_control = PTHREAD_ONCE_INIT;  typedef struct Tsd  {      pthread_t tid;      char *str;  } tsd_t;    //线程特定数据销毁函数,  //用来销毁每一个线程所指向的实际数据  void destructor_function(void *value)  {      free(value);      cout << "destructor ..." << endl;  }    //初始化函数, 将对key的初始化放入该函数中,  //能够保证inti_routine函数仅仅执行一次  void init_routine()  {      pthread_key_create(&key, destructor_function);      cout << "init..." << endl;  }    void *thread_routine(void *args)  {      pthread_once(&once_control, init_routine);        //设置线程特定数据      tsd_t *value = (tsd_t *)malloc(sizeof(tsd_t));      value->tid = pthread_self();      value->str = (char *)args;      pthread_setspecific(key, value);      printf("%s setspecific, address: %p\n", (char *)args, value);        //获取线程特定数据      value = (tsd_t *)pthread_getspecific(key);      printf("tid: 0x%x, str = %s\n", (unsigned int)value->tid, value->str);      sleep(2);        //再次获取线程特定数据      value = (tsd_t *)pthread_getspecific(key);      printf("tid: 0x%x, str = %s\n", (unsigned int)value->tid, value->str);        pthread_exit(NULL);  }    int main()  {      pthread_t tid1, tid2;      pthread_create(&tid1, NULL, thread_routine, (void *)"thread1");      pthread_create(&tid2, NULL, thread_routine, (void *)"thread2");        pthread_join(tid1, NULL);      pthread_join(tid2, NULL);      pthread_key_delete(key);        return 0;  }
执行结果例如以下:

init....

thread1 setspecific ,address: 0x7fe7a00008c0
tid: 0xa8192700, str = thread1
thread2 setspecific ,address :0x7fe7980008c0
tid: 0xa7991700 ,str = thread2
tid: 0xa8192700 ,str = thread1
tid: 0xa7001700 ,str = thread2
destructor...
destructor...

主线程创建了两个线程然后join 等待他们退出;给每一个线程的运行函数都是thread_routine,thread_routine 中调用了pthread_once,此函数表示假设当第一个线程调用它时会运行once_routine,然后从once_routine返回即pthread_once 返回,而接下去的其它线程调用它时将不再运行once_routine。此举是为了仅仅调用pthread_key_create 一次,即产生一个pthread_key_t 值。

在thread_routine 函数中自己定义了线程特定数据的类型。对于不同的线程来说TSD的内容不同,如果线程1在第一次打印完进入睡眠的时候。线程2也開始运行并调用pthread_setspecific 绑定线程2的TSD 和key_t,此时线程1调用pthread_getspecific 返回key_t 绑定的TSD指针,仍然是线程1的TSD指针,即尽管key_t 仅仅有一个,但每一个线程都有自己的TSD。

特定数据。具有128项,通过key-value实现,一个线程创建一个key,其它线程也会创建。可是并非指向的同一快内存。他们指向自己的数据。

这就是线程特定数据。

上述代码中,即使是Sleeep(2),线程1的数据并不会被线程2的数据所影响。由于是线程私有的。

当线程退出的时候会销毁2次,由于创建了两个线程。

当中tid 是线程的id,str 是传递给thread_routine 的參数,能够看到有两个不同的ptr,且destroy 调用两次。

另外,关于Linux/Unix线程私有数据实现思想:

请參考 http://blog.csdn.net/caigen1988/article/details/7901248。写的非常好。

转载于:https://www.cnblogs.com/gccbuaa/p/7074300.html

你可能感兴趣的文章
(菜鸟要飞系列)四,基于Asp.Net MVC5的后台管理系统(zTree绑定Json数据生成树)...
查看>>
JQuery判断数组中是否包含某个元素$.inArray("元素字符串", 数组名称);
查看>>
Gitlab 赋予某台机器git clone的权限 Deploy key
查看>>
python paramiko的使用介绍
查看>>
Python面试综合--DB相关
查看>>
jQuery实现列表框双向选择操作
查看>>
iOS 音频开发之CoreAudio
查看>>
java内部类
查看>>
禁止网页右键和复制,ctrl+a都不行。取消页面默认事件【全】。
查看>>
团队项目冲刺第九天
查看>>
个人作业1——四则运算题目生成程序(基于控制台)
查看>>
手机号码归属地查询,手机号码归属地批量查询
查看>>
C#自定义异常
查看>>
noip模拟赛#14
查看>>
C#读写三菱PLC和西门子PLC数据 使用TCP/IP 协议
查看>>
vue中moudles的作用及使用方法
查看>>
alpha版、beta版、rc版的意思
查看>>
负载均衡的常用算法
查看>>
JS版本 Bootstrap Modal
查看>>
Perl Coro初体检
查看>>