Posix线程编程指南(2) 线程私有数据
概念及作用
在单线程程序中,我们经常要用到"全局变量"以实现多个函数间共享数据。在多线程环境下,由于数据空间是共享的,因此全局变量也为所有线程所共有。但有时应用程序设计中有必要提供线程私有的全局变量,仅在某个线程中有效,但却可以跨多个函数访问,比如程序可能需要每个线程维护一个链表,而使用相同的函数操作,最简单的办法就是使用同名而不同变量地址的线程相关数据结构。这样的数据结构可以由Posix线程库维护,称为线程私有数据(Thread-specific Data,或TSD)。
创建和注销
Posix定义了两个API分别用来创建和注销TSD:
int pthread_key_create(pthread_key_t *key, void (*destr_function) (void *)) |
该函数从TSD池中分配一项,将其值赋给key供以后访问使用。如果destr_function不为空,在线程退出(pthread_exit())时将以key所关联的数据为参数调用destr_function(),以释放分配的缓冲区。
不论哪个线程调用pthread_key_create(),所创建的key都是所有线程可访问的,但各个线程可根据自己的需要往key中填入不同的值,这就相当于提供了一个同名而不同值的全局变量。在LinuxThreads的实现中,TSD池用一个结构数组表示:
static struct pthread_key_struct pthread_keys[PTHREAD_KEYS_MAX] = { { 0, NULL } }; |
创建一个TSD就相当于将结构数组中的某一项设置为"in_use",并将其索引返回给*key,然后设置destructor函数为destr_function。
注销一个TSD采用如下API:
int pthread_key_delete(pthread_key_t key) |
这个函数并不检查当前是否有线程正使用该TSD,也不会调用清理函数(destr_function),而只是将TSD释放以供下一次调用pthread_key_create()使用。在LinuxThreads中,它还会将与之相关的线程数据项设为NULL(见"访问")。
访问
TSD的读写都通过专门的Posix Thread函数进行,其API定义如下:
int pthread_setspecific(pthread_key_t key, const void *pointer) |
写入(pthread_setspecific())时,将pointer的值(不是所指的内容)与key相关联,而相应的读出函数则将与key相关联的数据读出来。数据类型都设为void *,因此可以指向任何类型的数据。
在LinuxThreads中,使用了一个位于线程描述结构(_pthread_descr_struct)中的二维void *指针数组来存放与key关联的数据,数组大小由以下几个宏来说明:
#define PTHREAD_KEY_2NDLEVEL_SIZE 32 |
也就是说,数据存放与一个32×32的稀疏矩阵中。同样,访问的时候也由key值经过类似计算得到数据所在位置索引,再取出其中内容返回。
使用范例
以下这个例子没有什么实际意义,只是说明如何使用,以及能够使用这一机制达到存储线程私有数据的目的。
#include <stdio.h> |
给例程创建两个线程分别设置同一个线程私有数据为自己的线程ID,为了检验其私有性,程序错开了两个线程私有数据的写入和读出的时间,从程序运行结果可以看出,两个线程对TSD的修改互不干扰。同时,当线程退出时,清理函数会自动执行,参数为tid。
Posix线程编程指南(2) 线程私有数据的更多相关文章
- Posix线程编程指南(4) 线程终止
线程终止方式 一般来说,Posix的线程终止有两种情况:正常终止和非正常终止.线程主动调用pthread_exit()或者从线程函数中return都将使线程正常退出,这是可预见的退出方式:非正常终止是 ...
- Posix线程编程指南(1) 线程创建与取消
线程创建 1.1 线程与进程 相对进程而言,线程是一个更加接近于执行体的概念,它可以与同进程中的其他线程共享数据,但拥有自己的栈空间,拥有独立的执行序列.在串行程序基础上引入线程和进程是为了提高程序的 ...
- Posix线程编程指南(3) 线程同步
互斥锁 尽管在Posix Thread中同样可以使用IPC的信号量机制来实现互斥锁mutex功能,但显然semphore的功能过于强大了,在Posix Thread中定义了另外一套专门用于线程同步的m ...
- Posix线程编程指南
Posix线程编程指南 Posix线程编程指南... 1 一线程创建与取消... 2 线程创建... 2 1.线程与进程... 2 2. 创建线程... 2 3. 线程创建属性... 2 4. 创建的 ...
- Posix线程编程指南(5)
Posix线程编程指南(5) 杨沙洲 原文地址:http://www.ibm.com/developerworks/cn/linux/thread/posix_threadapi/part5/ 杂项 ...
- Posix线程编程指南(4)
Posix线程编程指南(4) 杨沙洲 原文地址:http://www.ibm.com/developerworks/cn/linux/thread/posix_threadapi/part4/ 线程终 ...
- Posix线程编程指南(2)
这是一个关于Posix线程编程的专栏.作者在阐明概念的基础上,将向您详细讲述Posix线程库API.本文是第2篇将向您讲述线程的创建与取消. 一.概念及作用在单线程程序中,我们经常要用到"全 ...
- 转载:Posix线程编程指南(2)
概念及作用 在单线程程序中,我们经常要用到"全局变量"以实现多个函数间共享数据.在多线程环境下,由于数据空间是共享的,因此全局变量也为所有线程所共有.但有时应用程序设计中有必要提供 ...
- Posix线程编程指南(1)
这是一个关于Posix线程编程的专栏.作者在阐明概念的基础上,将向您详细讲述Posix线程库API.本文是第一篇将向您讲述线程的创建与取消. 一.线程创建 1.1 线程与进程相对进程而言,线程是一 ...
随机推荐
- Visual Studio 2010 更新NuGet Package Manager出错解决办法
在Visual Studio 2010的扩展管理器中发现NuGet Package Manger有最新版本更新提示,选择更新安装提示以下错误信息: 2013/4/25 1:11:48 - Micros ...
- JS组件系列——KnockoutJS用法
前言:出于某种原因,需要学习下Knockout.js,这个组件很早前听说过,但一直没尝试使用,这两天学习了下,觉得它真心不错,双向绑定的机制简直太爽了.今天打算结合bootstrapTable和Kno ...
- Spark RDD的依赖解读
在Spark中, RDD是有依赖关系的,这种依赖关系有两种类型 窄依赖(Narrow Dependency) 宽依赖(Wide Dependency) 以下图说明RDD的窄依赖和宽依赖 窄依赖 窄依赖 ...
- 使APP消除上方手机消息提示栏(显示WIFI,信号格那栏)消失的方法
public void toggleFullscreen(boolean fullScreen) { // fullScreen为true时全屏,否则相反 WindowManager.LayoutPa ...
- jquery 点击页面其他地方实现隐藏菜单功能
1.给页面文档添加一个点击事件函数,在函数内实现隐藏菜单功能. $('html').click(function(){//Hide the menus if visible});//用$(docume ...
- List GetEnumerator
static void Main() { List<int> list = new List<int>(); list.Add(); list.Add(); list.Add( ...
- 第十四章 调试及安全性(In .net4.5) 之 对称及非对称加密
1. 概述 本章内容包括:对称及非对称加密算法..net中的加密类.使用哈希操作.创建和管理签名认证.代码访问权限 和 加密字符串. 2. 主要内容 2.1 使用对称和非对称加密 ① 对称加密:使用同 ...
- 3.css中的颜色
css中颜色的设置形式主要有三种方式:颜色名称.十六进制代码和十进制代码. 在古老的 HTML4 时,颜色名称只有 16 种. 颜色名称 十六进制代码 十进制代码 含义 black #000000 ...
- Unity Scripting Tutorials 要点记录
(搬运自我在SegmentFault的博客) 这几天通过Unity官网的Unity Scripting Tutorials的视频学习Unity脚本,观看的过程中做了记录.现在,整理了一下笔记,供自己以 ...
- C语言如何 实现 下雪效果
题外话 前言 1.本文主要围绕 如何 在 控制台上 下起 一场 只有自己能看见的雪 2.是个简易跨平台的,主要是C语言 3.动画 采用 1s 40帧, 雪花具有 x轴速度和y轴速度 4.比较简单,可 ...