在多线程程序中。常常要用全局变量来实现多个函数间的数据共享。因为数据空间是共享的,因此全局变量也为全部线程共同拥有。

測试代码例如以下:

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h> int key = 100; //全局变量 void *helloworld_one(void *arg)
{
printf("the message is %s\n",(char *)arg);
key = 10;
printf("key=%d, the child id is %lu\n", key, pthread_self()); return NULL;
} void *helloworld_two(void *arg)
{
printf("the message is %s\n", (char *)arg);
sleep(1);
printf("key=%d, the child id is %lu\n", key, pthread_self()); return NULL;
} int main(int argc, char *argv[])
{
pthread_t thread_id_one;
pthread_t thread_id_two; //创建线程
pthread_create(&thread_id_one, NULL, helloworld_one, "helloworld_one");
pthread_create(&thread_id_two, NULL, helloworld_two, "helloworld_two"); //等待线程结束。回收资源
pthread_join(thread_id_one, NULL);
pthread_join(thread_id_two, NULL); return 0;
}

执行结果例如以下:

由执行结果能够看出,当中一个线程对全局变量的改动将影响到还有一个线程的訪问。

但有时应用程序设计中必要提供线程私有的全局变量,这个变量仅在线程中有效。但却能够跨过多个函数訪问。

比方在程序里可能须要每一个线程维护一个链表。而会使用同样的函数来操作这个链表,最简单的方法就是使用同名而不同变量地址的线程相关数据结构。这种数据结构能够由 Posix 线程库维护,成为线程私有数据 (Thread-specific Data,或称为 TSD)。

以下接口所需头文件:

#include <pthread.h>

1)创建线程私有数据

int pthread_key_create(pthread_key_t *key, void (*destructor)(void*));

功能:

创建一个类型为 pthread_key_t 类型的私有数据变量( key )。

參数:

key:在分配( malloc )线程私有数据之前,须要创建和线程私有数据相关联的键( key ),这个键的功能是获得对线程私有数据的訪问权。

destructor:清理函数名字( 如:fun )。当线程退出时,假设线程私有数据地址不是非 NULL,此函数会自己主动被调用。

该函数指针能够设成 NULL ,这样系统将调用默认的清理函数。

回调函数其定义例如以下:

void fun(void *arg)

{

// arg 为 key 值

}

返回值:

成功:0

失败:非 0

不论哪个线程调用 pthread_key_create(),所创建的 key 都是全部线程可訪问,但各个线程可依据自己的须要往 key 中填入不同的值,相当于提供了一个同名不同值的变量。

2)注销线程私有数据

int pthread_key_delete(pthread_key_t key);

功能:

注销线程私有数据。

这个函数并不会检查当前是否有线程正使用线程私有数据( key ),也不会调用清理函数 destructor() 。而仅仅是将线程私有数据( key )释放以供下一次调用 pthread_key_create() 使用。

參数:

key:待注销的私有数据。

返回值:

成功:0

失败:非 0

3)设置线程私有数据的关联

int pthread_setspecific(pthread_key_t key, const void *value);

功能:

设置线程私有数据( key ) 和 value 关联,注意,是 value 的值(不是所指的内容)和 key 相关联。

參数:

key:线程私有数据。

value:和 key 相关联的指针。

返回值:

成功:0

失败:非 0

4)读取线程私有数据所关联的值

void *pthread_getspecific(pthread_key_t key);

功能:

读取线程私有数据( key )所关联的值。

參数:

key:线程私有数据。

返回值:

成功:线程私有数据( key )所关联的值。

失败:NULL

演示样例代码例如以下:

// this is the test code for pthread_key
#include <stdio.h>
#include <pthread.h> pthread_key_t key; // 私有数据。全局变量 void echomsg(void *t)
{
printf("[destructor] thread_id = %lu, param = %p\n", pthread_self(), t);
} void *child1(void *arg)
{
int i = 10; pthread_t tid = pthread_self(); //线程号
printf("\nset key value %d in thread %lu\n", i, tid); pthread_setspecific(key, &i); // 设置私有数据 printf("thread one sleep 2 until thread two finish\n\n");
sleep(2);
printf("\nthread %lu returns %d, add is %p\n",
tid, *((int *)pthread_getspecific(key)), pthread_getspecific(key) );
} void *child2(void *arg)
{
int temp = 20; pthread_t tid = pthread_self(); //线程号
printf("\nset key value %d in thread %lu\n", temp, tid); pthread_setspecific(key, &temp); //设置私有数据 sleep(1);
printf("thread %lu returns %d, add is %p\n",
tid, *((int *)pthread_getspecific(key)), pthread_getspecific(key));
} int main(void)
{
pthread_t tid1,tid2;
pthread_key_create(&key, echomsg); // 创建 pthread_create(&tid1, NULL, child1, NULL);
pthread_create(&tid2, NULL, child2, NULL);
pthread_join(tid1, NULL);
pthread_join(tid2, NULL); pthread_key_delete(key); // 注销 return 0;
}

执行结果例如以下:

从执行结果来看。各线程对自己的私有数据操作互不影响。

也就是说。尽管 key 是同名且全局,但訪问的内存空间并非同一个。

本教程演示样例代码下载请点此处。

本文转自:《Linux高级程序设计》

5
0

Linux系统编程——线程私有数据的更多相关文章

  1. UNIX环境高级编程——线程私有数据

    线程私有数据(Thread-specific data,TSD):存储和查询与某个线程相关数据的一种机制. 在进程内的所有线程都共享相同的地址空间,即意味着任何声明为静态或外部变量,或在进程堆声明的变 ...

  2. linux系统编程--线程

    安装线程man page,命令:sudo apt-get install manpages-posix-dev 线程概念 什么是线程 LWP:light weight process 轻量级的进程,本 ...

  3. Linux系统编程 —线程同步概念

    同步概念 同步,指对在一个系统中所发生的事件之间进行协调,在时间上出现一致性与统一化的现象. 但是,对于不同行业,对于同步的理解略有不同.比如:设备同步,是指在两个设备之间规定一个共同的时间参考:数据 ...

  4. linux系统编程--线程同步

    同步概念 所谓同步,即同时起步,协调一致.不同的对象,对“同步”的理解方式略有不同. 如,设备同步,是指在两个设备之间规定一个共同的时间参考: 数据库同步,是指让两个或多个数据库内容保持一致,或者按需 ...

  5. LInux多线程编程----线程特定数据的处理函数

    1.pthread_key_t和pthread_key_create() 线程中特有的线程存储, Thread Specific Data .线程存储有什么用了?他是什么意思了?大家都知道,在多线程程 ...

  6. Linux系统编程 —线程属性

    在之前的章节中,我们在调用pthread_create函数创建线程时,第二个参数(即线程属性)都是设为NULL,即使用默认属性.一般情况下,使用默认属性已经可以解决我们开发过程中的大多数问题. 但是, ...

  7. Linux 系统编程 学习:11-线程:线程同步

    Linux 系统编程 学习:11-线程:线程同步 背景 上一讲 我们介绍了线程的属性 有关设置.这一讲我们来看线程之间是如何同步的. 额外安装有关的man手册: sudo apt-get instal ...

  8. [转] unix/linux下线程私有数据实现原理及使用方法

     在维护每个线程的私有数据的时候,我们可能会想到分配一个保存线程数据的数组,用线程的ID作为数组的索引来实现访问,但是有一个问题是系统生成的线程 ID不能保证是一个小而连续的整数,并且用数组实现的时候 ...

  9. ZT linux 线程私有数据之 一键多值技术

    这个原作者的这个地方写错了 且他举的例子非常不好.最后有我的修正版本 pthread_setspecific(key, (void *)&my_errno); linux 线程私有数据之一键多 ...

随机推荐

  1. 【MySQL】常见错误与经常使用命令的集锦

    [背景介绍]     在使用SQL Server数据库期间,想必大家一定都有过解决各种问题的经历了.非常多时候,都会在大家的博客中看到问题与解决方式. 如今开发使用的是MySQL数据库.如今来看,发现 ...

  2. Trafodion:Transactional SQL on HBase

    Trafodion: Transactional SQL on HBase HBase上实时分布式事务处理 介绍 HBase的SQL能力一直不足.Phoenix缺乏Join能力,eBay提出的kyli ...

  3. 软件project经验总结系列之三 - 计划阶段控制

    本文为软件project经验总结系列文章的第三篇.按照总论文章所设立的范围划分,本阶段重点讲述计划阶段的控制过程以及控制思路,笔者所站在的角度是乙方角度来进行表述整个阶段的推动过程,但对于甲方公司其基 ...

  4. windows下硬盘安装debian

    windows下硬盘安装debian 此方法在 windows8.1 + debian8.7.1 可用 配置系统安装镜像 1 在windows下格式化一个fat32的分区 2 把下载的debian-7 ...

  5. 洛谷P2660 zzc 种田

    题目背景 可能以后 zzc就去种田了. 题目描述 田地是一个巨大的矩形,然而zzc 每次只能种一个正方形,而每种一个正方形时zzc所花的体力值是正方形的周长,种过的田不可以再种,zzc很懒还要节约体力 ...

  6. Winform 获取相对路径 C#

    ///获取相对路径 ///例如:System.Windows.Forms.Application.StartupPath = "E:\App\CheckingMachine\QueryMac ...

  7. Emmet学习教程

    Emmet (前身为 Zen Coding) 是一个能大幅度提高前端开发效率的一个工具,Emmet是很成熟的并且非常适用于编写HTML/XML 和 CSS 代码的前端开发人员,但也可以用于编程语言.所 ...

  8. 【例7-15 UVA-1603】Square Destroyer

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 先预处理出所有的正方形(长度为1,2...n的)所包含哪些边. 然后记录每个正方形的应有边长和实际边长(有些边被删掉了); 然后搜的 ...

  9. ArcGIS 10 影像、栅格数据格式批量转换

    转自原文 ArcGIS 10 影像.栅格数据格式批量转换 在做三维场景的时候,经常会涉及多种不同格式DEM数据或者影像的转换,如ASCII.GRID.IMG.TIFF等等,遇到大数据量时,我们就需要批 ...

  10. jquery实现转盘抽奖

    jquery实现转盘抽奖 一.总结 一句话总结:这里环形转盘,环形的东西可以化成线性的,然后访问到哪个,给他加上背景为红的样式,用定时器开控制转盘的速度,函数执行的时间间隔越小,就运动的越快. 1.如 ...