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. 前后台Json的转换

    jsp:JSON.stringify(params):params:表示数组 servlet:Store store = (Store) JSONObject.toBean(JSONObject.fr ...

  2. C陷阱与缺陷 1

    1,符号之间的空白被忽略 符号中间不能嵌入空白 2,词法分析中的贪心法 a---b 和 a-- -b相同 和 a- --b不同 1 a=b/*p //根据贪心法 /*被解释成 注释符,便不再往下读,直 ...

  3. c 深度剖析 4

    1 预处理 1#define 1.不能用 #define 定义注释,因为注释先于预处理被处理. 2 .宏定义表达式 1,注意展开后结合顺序,尽量多加括号 2,常量定义时注意是否溢出 1 #define ...

  4. timus 1022 Genealogical Tree(拓扑排序)

    Genealogical Tree Time limit: 1.0 secondMemory limit: 64 MB Background The system of Martians’ blood ...

  5. JavaScript判断IE各版本最完美解决方案

    https://github.com/nioteam/jquery-plugins/issues/12 jQuery在1.9版本之前,提供了一个浏览器对象检测的属性$.browser,使用率极高.但是 ...

  6. Java——File(文件)

     public static void main(String[] args) { // getFile(); /* * 需求:  对指定目录进行所有内容的列出,(包含子目录中的内容) * */ ...

  7. network Driver , TDI(Transport Driver Interface) Drivers

    https://msdn.microsoft.com/en-us/library/windows/hardware/ff565094(v=vs.85).aspx https://msdn.micros ...

  8. HTTP头详解

    HTTP 头部解释 1. Accept:告诉WEB服务器自己接受什么介质类型,*/* 表示任何类型,type/* 表示该类型下的所有子类型,type/sub-type. 2. Accept-Chars ...

  9. WCF入门教程一[什么是WCF]

    一.概述 Windows Communication Foundation(WCF)是由微软发展的一组数据通信的应用程序开发接口,可以翻译为Windows通讯接口,它是.NET框架的一部分.由 .NE ...

  10. Python 统计IIS日志行数

    __author__ = 'Administrator' import codecs def blocks(file, size=65536): while True: b = file.read(s ...