1、pthread_key_t和pthread_key_create()

线程中特有的线程存储, Thread Specific Data 。线程存储有什么用了?他是什么意思了?大家都知道,在多线程程序中,所有线程共享程序中的变量。现在有一全局变量,所有线程都可以使用它,改变它的值。而如果每个线程希望能单独拥有它,那么就需要使用线程存储了。表面上看起来这是一个全局变量,所有线程都可以使用它,而它的值在每一个线程中又是单独存储的。这就是线程存储的意义。
   线程存储的具体用法:

(1)创建一个类型为 pthread_key_t 类型的变量。

(2)调用 pthread_key_create() 来创建该变量。该函数有两个参数,第一个参数就是上面声明的 pthread_key_t 变量,第二个参数是一个清理函数,用来在线程释放该线程存储的时候被调用。该函数指针可以设成 NULL ,这样系统将调用默认的清理函数。

(3)当线程中需要存储特殊值的时候,可以调用 pthread_setspcific() 。该函数有两个参数,第一个为前面声明的 pthread_key_t 变量,第二个为 void* 变量,这样你可以存储任何类型的值。

(4)如果需要取出所存储的值,调用 pthread_getspecific() 。该函数的参数为前面提到的 pthread_key_t 变量,该函数返回 void * 类型的值。

2、pthread_once 和 pthread_key

一次性初始化

有时候我们需要对一些posix变量只进行一次初始化,如线程键(我下面会讲到)。如果我们进行多次初始化程序就会出现错误。

在传统的顺序编程中,一次性初始化经常通过使用布尔变量来管理。控制变量被静态初始化为0,而任何依赖于初始化的代码都能测试该变量。如果变量值仍然为0,则它能实行初始化,然后将变量置为1。以后检查的代码将跳过初始化。

但是在多线程程序设计中,事情就变的复杂的多。如果多个线程并发地执行初始化序列代码,可能有2个线程发现控制变量为0,并且都实行初始化,而该过程本该仅仅执行一次。

如果我们需要对一个posix变量静态的初始化,可使用的方法是用一个互斥量对该变量的初始话进行控制。但有时候我们需要对该变量进行动态初始化,pthread_once就会方便的多。

有些事需要一次且仅需要一次执行。通常当初始化应用程序时,可以比较容易地将其放在main函数中。但当你写一个库时,就不能在main里面初始化了,你可以用静态初始化,但使用一次初始化(pthread_once_t)会比较容易些。

3、示例代码及运行结果:

  1. /*
  2. * ThreadSpecificData.c
  3. *
  4. * Created on: Aug 11, 2013
  5. * Author: root
  6. */
  7. #include <stddef.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <pthread.h>
  12.  
  13. #if 0
  14. char * str_accumulate(char *s){
  15. static char accu[] = {};
  16. strcat(accu, s);
  17. return accu;
  18. }
  19. #endif
  20.  
  21. static pthread_key_t str_key;
  22. static pthread_once_t str_alloc_key_once = PTHREAD_ONCE_INIT;
  23. static void str_alloc_key();
  24. static void str_alloc_destroy_accu(void * accu);
  25. char * str_accumulate(const char *s){
  26. char * accu;
  27. pthread_once(&str_alloc_key_once, str_alloc_key);
  28. accu = (char*)pthread_getspecific(str_key);
  29. if(accu == NULL){
  30. accu = malloc();
  31. if(accu == NULL) return NULL;
  32. accu[] = ;
  33. pthread_setspecific(str_key, (void*)accu);
  34. printf("Thread %lx:allocating buffer at %p\n", pthread_self(), accu);
  35. }
  36. strcat(accu, s);
  37. return accu;
  38. }
  39.  
  40. static void str_alloc_key(){
  41. pthread_key_create(&str_key, str_alloc_destroy_accu);
  42. printf("Thread %lx:allocated key %d\n", pthread_self(), str_key);
  43. }
  44.  
  45. //thread specific data is NULL, this function will be called by this thread.
  46. static void str_alloc_destroy_accu(void *accu){
  47. printf("Thread %lx:freeing buffer at %p\n", pthread_self(), accu);
  48. free(accu);
  49. }
  50. void * process(void * arg){
  51. char * str;
  52. str = str_accumulate("Result of ");
  53. str = str_accumulate((char*)arg);
  54. str = str_accumulate(" thread");
  55. printf("Thread %lx:\"%s\"\n", pthread_self(), str);
  56. return NULL;
  57. }
  58.  
  59. int main(){
  60. char * str;
  61. pthread_t th1,th2;
  62. str = str_accumulate("Main process Result of");
  63. pthread_create(&th1, NULL, process, (char*)"first");
  64. pthread_create(&th2, NULL, process, (char*)"second");
  65. str = str_accumulate("initial thread");
  66. printf("Thread %lx:\"%s\"\n", pthread_self(), str);
  67. pthread_join(th1, NULL);
  68. pthread_join(th2, NULL);
  69. return ;
  70. }

运行结果是:

  1. Thread b757b6c0:allocated key
  2. Thread b757b6c0:allocating buffer at 0x9a99008
  3. Thread b757b6c0:"Main process Result ofinitial thread"
  4. Thread b6d79b40:allocating buffer at 0xb6400468
  5. Thread b6d79b40:"Result of second thread"
  6. Thread b6d79b40:freeing buffer at 0xb6400468
  7. Thread b757ab40:allocating buffer at 0xb6400468
  8. Thread b757ab40:"Result of first thread"
  9. Thread b757ab40:freeing buffer at 0xb6400468

LInux多线程编程----线程特定数据的处理函数的更多相关文章

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

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

  2. Linux多线程编程——线程的创建与退出

    POSIX线程标准:该标准定义了创建和操纵线程的一整套API.在类Unix操作系统(Unix.Linux.Mac OS X等)中,都使用Pthreads作为操作系统的线程.Windows操作系统也有其 ...

  3. Linux 多线程编程--线程退出

    今天分析项目中进程中虚存一直增长问题,运行10个小时虚存涨到121G ,RSS占用为16G 非常恐怖. Valgrind测试无内存泄漏. 内存32G 64bit系统信息如下: Linux线程使用方式是 ...

  4. Linux多线程编程——线程的同步

    POSIX信号量 posix信号量不同于IPC中的信号量  常用的posix信号量函数   #include <semaphore.h> int sem_init(sem_t* sem,i ...

  5. LInux多线程编程----线程属性pthread_attr_t

    1.每个POSIX线程有一个相连的属性对象来表示属性.线程属性对象的类型是pthread_attr_t,pthread_attr_t 在文件/usr/include/bits/pthreadtypes ...

  6. 线程特定数据TSD总结

    一线程的本质 二线程模型的引入 三线程特定数据 四关键函数说明 五刨根问底啥原理 六私有数据使用演示样例 七參考文档 一.线程的本质 Linux线程又称轻量进程(LWP),也就说线程本质是用进程之间共 ...

  7. Linux多线程实践(4) --线程特定数据

    线程特定数据 int pthread_key_create(pthread_key_t *key, void (*destr_function) (void *)); int pthread_key_ ...

  8. Linux多线程编程初探

    Linux线程介绍 进程与线程 典型的UNIX/Linux进程可以看成只有一个控制线程:一个进程在同一时刻只做一件事情.有了多个控制线程后,在程序设计时可以把进程设计成在同一时刻做不止一件事,每个线程 ...

  9. ZT 为什么pthread_cond_t要和pthread_mutex_t同时使用 || pthread/Linux多线程编程

    为什么线程同步的时候pthread_cond_t要和pthread_mutex_t同时使用 (2009-10-27 11:07:23) 转载▼ 标签: 杂谈 分类: 计算机 举一个例子(http:// ...

随机推荐

  1. ThinkPHP示例:图片上传

    ThinkPHP示例之图片上传,包括图片上传.数据库保存.缩略图生成以及图片水印功能演示.首先需要下载框架核心,然后把示例解压到Web根目录下面,并修改入口文件中的框架入口文件的位置.导入示例目录下面 ...

  2. AcWing 208. 开关问题 (高斯消元+状压)打卡

    有N个相同的开关,每个开关都与某些开关有着联系,每当你打开或者关闭某个开关的时候,其他的与此开关相关联的开关也会相应地发生变化,即这些相联系的开关的状态如果原来为开就变为关,如果为关就变为开. 你的目 ...

  3. 【进阶技术】一篇文章搞掂:Docker

    注意!!注意系统内存,一开始我使用阿里云1核1G系统,各种问题,搞了几天,原来是内存不足 一.使用VM虚拟机,安装CentOS7.X系统,并安装和使用Docker 1.1.虚拟机安装CentOS7.X ...

  4. hibernate.Criteria分页排序模糊查询

    org.hibernate.Criteria criteria = simpleDAO.getSession().createCriteria(Event.class); Criterion c = ...

  5. Win10+CentOS7双系统引导修复

    在有Win10的系统下安装了CentOS7后,CentOS7的引导并不会像CentOS6一样自动加载入Win10驱动.难道是grub2不能引导Win驱动?查了一下资料原来是CentOS不能识别Win1 ...

  6. MATLAB图像uint8,uint16,double, rgb转灰度解释

    1.uint8,uint16与double 为了节省存储空间,matlab为图像提供了特殊的数据类型uint8(8位无符号整数),以此方式存储的图像称作8位图像.matlab读入图像的数据是uint8 ...

  7. Matplotlib ValueError: _getfullpathname: embedded null character

    Traceback (most recent call last): File "<stdin>", line 1, in <module> File &q ...

  8. ollvm 编译

    ollvm 的编译相对 llvm 更简单, 1:下载ollvm代码,去 https://github.com/obfuscator-llvm/obfuscator/tree/llvm-4.0 下载,并 ...

  9. 《代码大全2》读书笔记 Week8

    这一周博主阅读了<代码大全2>第11章至第13章,第三部分——"变量"就结束了,第四部分作者将转入语句的讨论. 第十一章作者详细阐述了变量名的有效命名规则,第十二和十三 ...

  10. Linux环境安装Nginx步骤

    centos7平台编译环境使用如下指令安装: 1. 安装make: yum -y install gcc automake autoconf libtool make 2. 安装g++: yum -y ...