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 * 类型的值。
下面是前面提到的函数的原型:
int pthread_setspecific(pthread_key_t key, const void *value);
void *pthread_getspecific(pthread_key_t key);
int pthread_key_create(pthread_key_t *key, void (*destructor)(void*));
下面是一个如何使用线程存储的例子:

Code#include <malloc.h>

#include <pthread.h>

#include <stdio.h>

/* The key used to associate a log file pointer with each thread. */

static pthread_key_t thread_log_key;  

/* Write MESSAGE to the log file for the current thread. */

void write_to_thread_log (const char* message)  

{
FILE* thread_log = (FILE*) pthread_getspecific (thread_log_key); fprintf (thread_log, “%s\n”, message);
} /* Close the log file pointer THREAD_LOG. */ void close_thread_log (void* thread_log) {
fclose ((FILE*) thread_log);
} void* thread_function (void* args) {
char thread_log_filename[20]; FILE* thread_log; /* Generate the filename for this thread’s log file. */ sprintf (thread_log_filename, “thread%d.log”, (int) pthread_self ()); /* Open the log file. */ thread_log = fopen (thread_log_filename, “w”); /* Store the file pointer in thread-specific data under thread_log_key. */ pthread_setspecific (thread_log_key, thread_log); write_to_thread_log (“Thread starting.”); /* Do work here... */ return NULL;
} int main () { int i; pthread_t threads[5]; /* Create a key to associate thread log file pointers in thread-specific data. Use close_thread_log to clean up the file pointers. */ pthread_key_create (&thread_log_key, close_thread_log); /* Create threads to do the work. */ for (i = 0; i < 5; ++i) pthread_create (&(threads[i]), NULL, thread_function, NULL); /* Wait for all threads to finish. */ for (i = 0; i < 5; ++i) pthread_join (threads[i], NULL); return 0; }

最后说一下线程的本质。
其实在Linux 中,新建的线程并不是在原先的进程中,而是系统通过一个系统调用clone() 。该系统copy 了一个和原先进程完全一样的进程,并在这个进程中执行线程函数。不过这个copy 过程和fork 不一样。copy 后的进程和原先的进程共享了所有的变量,运行环境(clone的实现是可以指定新进程与老进程之间的共享关系,100%共享就表示创建了一个线程)。这样,原先进程中的变量变动在copy 后的进程中便能体现出来。

参考链接:http://blog.csdn.net/lwfcgz/article/details/37570667

http://blog.csdn.net/lmh12506/article/details/8452700

pthread_key_t和pthread_key_create()详解的更多相关文章

  1. Linq之旅:Linq入门详解(Linq to Objects)

    示例代码下载:Linq之旅:Linq入门详解(Linq to Objects) 本博文详细介绍 .NET 3.5 中引入的重要功能:Language Integrated Query(LINQ,语言集 ...

  2. 架构设计:远程调用服务架构设计及zookeeper技术详解(下篇)

    一.下篇开头的废话 终于开写下篇了,这也是我写远程调用框架的第三篇文章,前两篇都被博客园作为[编辑推荐]的文章,很兴奋哦,嘿嘿~~~~,本人是个很臭美的人,一定得要截图为证: 今天是2014年的第一天 ...

  3. EntityFramework Core 1.1 Add、Attach、Update、Remove方法如何高效使用详解

    前言 我比较喜欢安静,大概和我喜欢研究和琢磨技术原因相关吧,刚好到了元旦节,这几天可以好好学习下EF Core,同时在项目当中用到EF Core,借此机会给予比较深入的理解,这里我们只讲解和EF 6. ...

  4. Java 字符串格式化详解

    Java 字符串格式化详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 文中如有纰漏,欢迎大家留言指出. 在 Java 的 String 类中,可以使用 format() 方法 ...

  5. Android Notification 详解(一)——基本操作

    Android Notification 详解(一)--基本操作 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Notification 文中如有纰 ...

  6. Android Notification 详解——基本操作

    Android Notification 详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 前几天项目中有用到 Android 通知相关的内容,索性把 Android Notificatio ...

  7. Git初探--笔记整理和Git命令详解

    几个重要的概念 首先先明确几个概念: WorkPlace : 工作区 Index: 暂存区 Repository: 本地仓库/版本库 Remote: 远程仓库 当在Remote(如Github)上面c ...

  8. Drawable实战解析:Android XML shape 标签使用详解(apk瘦身,减少内存好帮手)

    Android XML shape 标签使用详解   一个android开发者肯定懂得使用 xml 定义一个 Drawable,比如定义一个 rect 或者 circle 作为一个 View 的背景. ...

  9. Node.js npm 详解

    一.npm简介 安装npm请阅读我之前的文章Hello Node中npm安装那一部分,不过只介绍了linux平台,如果是其它平台,有前辈写了更加详细的介绍. npm的全称:Node Package M ...

随机推荐

  1. 使用npoi.dll导出数据到excel

    .net数据导出excel数据有多种方法,最常用的就是使用office组件,但随之而来的问题也很棘手,又要调权限又要确定是否安装office很是麻烦,最近一个项目中也有数据导出功能,随使用excel模 ...

  2. leetcode 101 Symmetric Tree ----- java

    Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center). For e ...

  3. Apache配置站点根目录、用户目录及页面访问属性

    一.配置站点根目录及页面访问属性 DocumentRoot "/www/htdoc" <Directory "/www/htdoc"> Option ...

  4. cloudera安装报错 socket.gaierror: [Errno -2] Name or service not known

    有时候安装cloudera会报socket.gaierror: [Errno -2] Name or service not known,或者服务器可能IP或mac地址冲突会引发次错误.导致机器服务不 ...

  5. Linux驱动设计编译错误信息集锦

    1.warning: passing argument 2 of 'request_irq' from incompatible pointer type http://blog.sina.com.c ...

  6. Java——线程间通信问题

     wait和sleep区别: 1.wait可以指定时间可以不指定.     sleep必须指定时间. 2.在同步时,对cpu的执行权和锁的处理不同.     wait:释放执行权,释放锁.     ...

  7. Qt QTreeWidget 树形结构实现(转)

    Qt中实现树形结构可以使用QTreeWidget类,也可以使用QTreeView类,QTreeWidget继承自QTreeView类.树形效果如下图所示: 这是怎么实现的呢?还有点击节点时会有相应的事 ...

  8. #你好Unity3D#Hierarchy视图监听gameObject点击事件

    今天无意间又找到了个好方法     1 2 3 4 5 6 7 8 9 10 [InitializeOnLoadMethod] static void Start () {   Selection.s ...

  9. PostgreSQL: Query for location of global tablespace?

    Q: I have been trying to make our database clients pro-active about not filling up the partition on ...

  10. Linux查看端口使用状态、关闭端口方法

    前提:首先你必须知道,端口不是独立存在的,它是依附于进程的.某个进程开启,那么它对应的端口就开启了,进程关闭,则该端口也就关闭了.下次若某个进程再次开启,则相应的端口也再次开启.而不要纯粹的理解为关闭 ...