Posix线程编程指南(2)——线程私有数据

多线程私有数据pthread_key_create 阅读详情

Posix线程编程指南(2)——线程私有数据

级别: 初级

杨沙洲 (pubb@163.net)

引自:http://www.ibm.com/developerworks/cn/linux/thread/posix_threadapi/part2/

2001 年 10 月 01 日

        这是一个关于Posix线程编程的专栏。作者在阐明概念的基础上,将向您详细讲述Posix线程库API。本文是第二篇将向您讲述线程的私有数据。

概念及作用

在单线程程序中,我们经常要用到"全局变量"以实现多个函数间共享数据。在多线程环境下,由于数据空间是共享的,因此全局变量也为所有线程所共有。但有时应用程序设计中有必要提供线程私有的全局变量,仅在某个线程中有效,但却可以跨多个函数访问,比如程序可能需要每个线程维护一个链表,而使用相同的函数操作,最简单的办法就是使用同名而不同变量地址的线程相关数据结构。这样的数据结构可以由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)
void * pthread_getspecific(pthread_key_t key)

写入(pthread_setspecific())时,将pointer的值(不是所指的内容)与key相关联,而相应的读出函数则将与key相关联的数据读出来。数据类型都设为void *,因此可以指向任何类型的数据。

在LinuxThreads中,使用了一个位于线程描述结构(_pthread_descr_struct)中的二维void *指针数组来存放与key关联的数据,数组大小由以下几个宏来说明:

 

#define PTHREAD_KEY_2NDLEVEL_SIZE       32
#define PTHREAD_KEY_1STLEVEL_SIZE /
((PTHREAD_KEYS_MAX + PTHREAD_KEY_2NDLEVEL_SIZE - 1)
/ PTHREAD_KEY_2NDLEVEL_SIZE)
其中在/usr/include/bits/local_lim.h中定义了PTHREAD_KEYS_MAX为1024,因此一维数组大小为32。而具体存放的位置由key值经过以下计算得到:
idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE
idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE

也就是说,数据存放与一个32×32的稀疏矩阵中。同样,访问的时候也由key值经过类似计算得到数据所在位置索引,再取出其中内容返回。

使用范例

以下这个例子没有什么实际意义,只是说明如何使用,以及能够使用这一机制达到存储线程私有数据的目的。

#include <stdio.h>
#include <pthread.h>
pthread_key_t key;
void echomsg(int t)
{
printf("destructor excuted in thread %d,param=%d/n",pthread_self(),t);
}
void * child1(void *arg)
{
int tid=pthread_self();
printf("thread %d enter/n",tid);
pthread_setspecific(key,(void *)tid);
sleep(2);
printf("thread %d returns %d/n",tid,pthread_getspecific(key));
sleep(5);
}
void * child2(void *arg)
{
int tid=pthread_self();
printf("thread %d enter/n",tid);
pthread_setspecific(key,(void *)tid);
sleep(1);
printf("thread %d returns %d/n",tid,pthread_getspecific(key));
sleep(5);
}
int main(void)
{
int tid1,tid2;
printf("hello/n");
pthread_key_create(&key,echomsg);
pthread_create(&tid1,NULL,child1,NULL);
pthread_create(&tid2,NULL,child2,NULL);
sleep(10);
pthread_key_delete(key);
printf("main thread exit/n");
return 0;
}

给例程创建两个线程分别设置同一个线程私有数据为自己的线程ID,为了检验其私有性,程序错开了两个线程私有数据的写入和读出的时间,从程序运行结果可以看出,两个线程对TSD的修改互不干扰。同时,当线程退出时,清理函数会自动执行,参数为tid。

 

关于作者

 

杨沙洲,男,现攻读国防科大计算机学院计算机软件方向博士学位。您可以通过电子邮件 pubb@163.net跟他联系。

 

linux中的线程局部存储(TLS)实现线程间的同步和互斥pthread_key_create、pthread_setspecific、pthread_getspecific 由于线程局部存储是基于操作系统的特性,因此它可能会受到操作系统实现的影响。不同的操作系统可能会有不同的线程局部存储实现和限制。 阅读详情

相关推荐

DDR内存Prefetch机制深度解析:从DDR1到DDR5的带宽演进与工程实践

内存带宽是衡量存储系统性能的关键指标,而DRAM内部电容充放电速度受物理限制,导致核心频率难以提升。为突破这一瓶颈,DDR引入了Prefetch(预取)机制,通过一次从存储阵列读取多份数据再分批送出,实现内外频率解耦。本文从DDR1的2n Prefetch到DDR3的8n,再到DDR4的Bank Group并行架构与DDR5的16n子通道设计,系统梳理了四代DDR内存如何靠Prefetch持续翻倍带宽。同时剖析了该机制带来的延迟代价——绝对延迟长期徘徊在10ns左右,以及行缓冲冲突对随机访问性能的影响。结合

cuiji1279的博客 330

Linux多线程之pthread_key_create()

本文介绍了pthread_key_create()函数在多线程编程中的基本概念、功能和使用方法。通过了解pthread_key_create()的使用,可以更好地管理多线程编程中的线程特定数据,避免数据竞争和其他相关问题的发生。在使用pthread_key_create()函数时,需要注意以下几点:1 键的范围pthread_key_t类型的键的范围通常是有限的,具体取决于系统的实现。因此,在创建和使用键时,应确保键的数量不会超出系统限制。2 线程特定数据的初始化。

Lid_23的博客 2468

【C/C++多线程编程之十】pthread线程私有数据

多线程编程之线程私有数据      Pthread是 POSIX threads 的简称,是POSIX的线程标准。         线程同步从互斥量【C/C++多线程编程之六】pthread互斥量,信号量【C/C++多线程编程之七】pthread信号量,条件变量【C/C++多线程编程之八】pthread条件变量,读写锁【C/C++多线程编程之九】pthread读写锁,多线程的同

Jiangwei的专栏 7196

pthread_key_t和pthread_key_create()详解

现在有一全局变量,所有线程都可以使用它,改变它的值。表面上看起来这是一个全局变量,所有线程都可以使用它,而它的值在每一个线程中又是单独存储的。这就是线程存储的意义。该函数有两个参数,第一个参数就是上面声明的pthread_key_t变量,第二个参数是一个清理函数,用来在线程释放该线程存储的时候被调用。该函数有两个参数,第一个为前面声明的pthread_key_t变量,第二个为void*变量,这样你可以存储任何类型的值。该函数的参数为前面提到的pthread_key_t变量,该函数返回void *类型的值。

qq_34888036的博客 1843

VLA算法总结对比——RT1 / RT2 / Pi0 / Octo/ RDT / OpenVLA

本文主要针最近比较经典的VLA算法进行对比总结,暂不涉及到代码细节和实验细节上的展开,仅仅是从大面上掌握下目前VLA的一些思路和方法。

weixin_44580210的博客 9496

SAP移动类型

SAP移动类型移动类型定义 移动类型定义

qq_20593197的博客 6204

pthread_key_create函数

函数原型:  int pthread_key_create(pthread_key_t *key, void(*destructor)(void*)); 功能:  分配用于表示进程中线程特定数据的键,键对进程中的所有线程来说是全局的。创建线程特定数据时,所有线程最初 都具有与该键关联的NULL值。POSIX要求系统至少支持128TSD 头文件:#include pthread非linux

Crazy_Bear 4511

【RK3588 NPU性能调优实战】多线程异步推理YOLOv5,榨干6TOPS算力

本文详细解析了如何在RK3588 NPU上通过多线程异步推理优化YOLOv5目标检测性能,实现6TOPS算力的最大化利用。通过线程池设计、流水线化帧处理及避开内存带宽瓶颈等技巧,将NPU利用率从30%提升至82%,帧率显著提高至61.2FPS。文章还提供了环境配置、代码实现及性能对比数据,助力开发者高效部署AI模型。

weixin_29034963的博客 340

Posix线程编程指南(2)线程私有数据

 

1059

【CIC-IDS数据集+机器学习】实现网络流量异常检测

本项目基于CIC-IDS数据集,使用多种机器学习算法实现网络流量异常检测系统。项目采用了完整的机器学习工作流程,从数据预处理到模型部署,实现了高精度的网络入侵检测。

XiaoMu_001的博客 1935

文华财经公式编程:麦语言简介及基础语法

文华财经公式语言(麦语言)是一种专门用于金融领域的编程语言,它是由文华财经公司开发的。提供了丰富的金融计算函数和数据处理功能,可以用于金融市场的数据分析、模型建立和交易策略的开发。例1:A:CLOSE;// 定义变量A为收盘价(盘中k线没有走完的时候A为最新价)。例2:MA5:=MA(C,5);// 定义收盘价的5周期均线(C为CLOSE简写)。例3:A:=REF(C,1);// 取得前一根k线的收盘价。

超哥量化的博客 1万+

Posix线程编程指南(2)-线程私有数据

杨沙洲2001 年 10 月这是一个关于Posix线程编程的专栏。作者在阐明概念的基础上,将向您详细讲述Posix线程库API。本文是第二篇将向您讲述线程的私有数据。一.概念及作用在单线程程序中,我们经常要用到"全局变量"以实现多个函数间共享数据。在多线程环境下,由于数据空间是共享的,因此全局变量也为所有线程所共有。但有时应用程序设计中有必要提供线程私有的全局变量,仅在某个线程中有效,

1419

Pinocchio 安装教程|机器人学的必备库

安装pinocchio,不要安装pip3 install pinocchio!

darcsdn 1660

Posix线程编程指南(2)--线程私有数据

Posix线程编程指南(2)--线程私有数据from: http://blog.chinaunix.net/u2/61627/showart_682499.html2001 年 10 月 01 日这是一个关于Posix线程编程的专栏。作者在阐明概念的基础上,将向您详细讲述Posix线程库API。本文是第二篇

shark0001的专栏 491

LangChain Message 官方文档

消息是聊天模型中的基本通信单位。它们用于表示聊天模型的输入和输出,以及与对话相关的其他上下文或元数据。每条消息都包含一个角色(如“用户”、“助手”)和内容(如文本或多模态数据),并可能包含根据不同聊天模型提供商而有所不同的附加元数据。LangChain 提供了一个统一的消息格式,可以跨不同聊天模型使用,简化用户在不同模型之间切换时所需关注的消息格式差异。

AI Agent 首席体验官 896

嵌入式工程师成长之路(5)——板子调试

USB2514集线器调试总结说说USB连接线USB数据线上的“疙瘩”:原来有这么大用处!

云轩阁 4万+

Posix线程编程指南(2) 线程私有数据

概念及作用 在单线程程序中,我们经常要用到"全局变量"以实现多个函数间共享数据。在多线程环境下,由于数据空间是共享的,因此全局变量也为所有线程所共有。但有时应用程序设计中有必要提供线程私有的全局变量,仅在某个线程中有效,但却可以跨多个函数访问,比如程序可能需要每个线程维护一个链表,而使用相同的函数操作,最简单的办法就是使用同名而不同变量地址的线程相关数据结构。这样的数据结构可以由Posix线程库...

weixin_30325971的博客 77

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

Posix线程私有数据

在单线程程序中,我们经常要用到"全局变量"以实现多个函数间共享数据。在多线程环境下,由于数据空间是共享的,因此全局变量也为所有线程所共有。但有时应用程序设计中有必要提供线程私有的全局变量,仅在某个线程中有效,但却可以跨多个函数访问.     我们想想使用什么方法可以做到这一点。 1.全局变量为进程中所有线程可见,是否有方法可以缩小其可见度,使其只在某个线程中可见 2.函数模块中的自动变量

停止更新,迁移至ykpeng.com 667

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Windows下 POSIX 线程编程

1. POSIX 标准        POSIX是Portable Operating System Interface of Unix的缩写。由IEEE(Institute of Electrical and Electronic Engineering)开发,由ANSI和ISO标准化。        POSIX的诞生和Unix的发展是密不可分的,Unix于70年代诞生于Bell lab,并

Kevin的专栏 7257

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Posix线程编程指南(2)

Posix线程编程指南(2) 杨沙洲 原文地址:http://www.ibm.com/developerworks/cn/linux/thread/posix_threadapi/part2/ 线程私有数据 这是一个关于Posix线程编程的专栏。作者在阐明概念的基础上,将向您详细讲述Posix线程库API。本文是第二篇将向您讲述线程的私有数据。 概念及作用 在单线程程序中,我们经...

156

Posix线程编程指南

Posix线程编程指南 线程创建1.1 线程与进程相对进程而言,线程是一个更加接近于执行体的概念,它可以与同进程中的其他线程共享数据,但拥有自己的栈空间,拥有独立的执行序列。在串行程序基础上引入线程和进程是为了提高程序的并发度,从而提高程序运行效率和响应时间。线程和进程在使用上各有优缺点:线程执行开销小,但不利于资源的管理和保护;而进程正相反。同时,线程适合于在SMP机器上运行

lne818的专栏 1793

【Linux系统编程】多线程编程-POSIX线程

在Linux中,线程是系统调度的基本单位,是进程中的一个执行流。线程共享进程的资源(如内存空间、文件描述符等),但拥有独立的执行上下文(如栈、寄存器等)。

Stark的博客 1594

POSIX线程编程实战指南

本文全面介绍POSIX线程(pthreads)编程,涵盖核心概念和实战应用。主要内容包括:线程创建(pthread_create)与等待(pthread_join)、线程属性设置、资源回收(pthread_detach)等基础操作;重点讲解线程同步机制,包括互斥锁(mutex)和条件变量(condition variables)的实现原理与使用场景;还涉及线程局部存储、取消机制和异常处理等高级特性。

m0_70691405的博客 838

【Linux系统编程】线程私有数据

00. 目录 文章目录00. 目录01. 线程之间共享数据02. 线程私有数据2.1 创建线程私有数据2.2 销毁线程私有数据2.3 关联线程私有数据成员2.4 读取线程私有数据所关联的值03. 案例实践04. 附录 01. 线程之间共享数据 在多线程程序中,经常要用全局变量来实现多个函数间的数据共享。由于数据空间是共享的,因此全局变量也为所有线程共有。 测试代码: #include <st...

C/C++软件工程师、嵌入式软件工程师、物联网研发工程师、C/C++讲师、物联网讲师、嵌入式讲师、鸿蒙讲师---欢迎大家一起交流(私信添加博主微信) 1858
上一篇: Posix线程编程指南(1)---线程创建与取消
下一篇: Posix线程编程指南(3)——线程同步
suppercom
博客等级 码龄22年 4粉丝 3原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值