posix多线程--线程私有数据
1.当多个线程共享一个变量时,将该变量定义为静态或外部变量,使用互斥量确保共享变量的安全访问。
如果每个线程都需要一个私有变量值,则该值成为线程的私有数据。程序创建一个键,每个线程独立地设定或得到自己的键值,各线程间私有数据互不影响。
2.建立线程私有数据
int pthread_key_create(pthread_key_t *key,void (*destructor)(void *));
int pthread_key_delete(pthread_key_t key);
int pthread_setspecific(pthread_key_t key,void *value);
void *pthread_getspecific(pthread_key_t key);
私有数据键,若多次创建,会覆盖掉前面创建的键,对应的键值也将永远丢失。
使用pthread_key_delete释放一个私有数据键时,必须保证所有线程都不在持有该键的值。
更好的做法是不释放线程私有数据键,因为线程私有数据键最多可达128个,很少有程序需要这么多的树木,没有必要手动释放。
代码示例如下:
创建数据键,设置键值,获取键值
#include<stdio.h>
#include<pthread.h>
typedef struct tsd_tag
{
pthread_t tid;
char *string;
}tsd_t;
pthread_key_t tsd_key;
pthread_once_t key_once = PTHREAD_ONCE_INIT;
void one_routine(void)
{
pthread_key_create(&tsd_key,NULL);;
}
void *thread_routine(void *arg)
{
pthread_once(&key_once,one_routine);
tsd_t *value;
value = (tsd_t*)malloc(sizeof(tsd_t));
pthread_setspecific(tsd_key,value);
value->tid = pthread_self();
value->string = (char*)arg;
value=(tsd_t*)pthread_getspecific(tsd_key);
sleep();
value=(tsd_t*)pthread_getspecific(tsd_key);
printf("%s done...\n",value->string);
}
int main(void)
{
pthread_t tid1,tid2;
pthread_create(&tid1,NULL,thread_routine,"thread 1");
pthread_create(&tid2,NULL,thread_routine,"thread 2");
pthread_exit(NULL);
}
3.destructor函数
destructor函数仅仅当线程终止时被调用。当线程终止时,pthreads调用键的destructor函数前,将线程私有数据置为NULL,所以若线程私有数据值是堆存储的地址,并且想在destructor函数中释放,必须使用传递给destructor的参数,而不是pthread_getspecific的参数。可以自定义destructor函数。
键值为NULL意味着线程对应该键值不再有值,而不是赋空值。否则若随后调用pthread_key_create建立该键,线程将会收到旧值。
线程私有数据键的destructor函数在键值替换的时候不会被调用。即,如果在堆中将一个结构的指针作为键值,又分配一个新结构,并将新结构指针赋给相同数据键,则指向旧结构的指针不会调用destructor函数。
代码示例如下:
三个线程的私有变量数据,自定义destructor函数,在线程结束后,释放堆存储,在所有线程结束后,销毁私有数据键。
#include<stdio.h>
#include<pthread.h>
typedef struct private_tag
{
pthread_t tid;
char *string;
}private_t;
pthread_key_t key;
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
long counter = ;
void key_destructor(void *value)
{
private_t *private = (private_t*)value;
printf("thread \"%s\" exiting...\n",private->string);
free(value);
pthread_mutex_lock(&mutex);
counter--;
if(counter<=)
{
pthread_key_delete(key);
printf("key deleted...\n");
}
pthread_mutex_unlock(&mutex);
}
void *key_get(void)
{
void *value;
value = pthread_getspecific(key);
if(value==NULL)
{
printf("malloc\n");
value = malloc(sizeof(private_t));
pthread_setspecific(key,(void*)value);
}
return value;
}
void *thread_routine(void *arg)
{
private_t *value;
value = (private_t*)key_get();
value->tid = pthread_self();
value->string = (char*)arg;
printf("thread \"%s\" starting...\n",value->string);
sleep();
return NULL;
}
int main(void)
{
pthread_t tid1,tid2;
private_t *value;
pthread_key_create(&key,key_destructor);
counter = ;
value = (private_t *)key_get();
value->tid = pthread_self();
value->string = "Main thread";
pthread_create(&tid1,NULL,thread_routine,"Thread 1");
pthread_create(&tid2,NULL,thread_routine,"Thread 2");
printf("exiting\n");
pthread_exit(NULL);
}
posix多线程--线程私有数据的更多相关文章
- Posix线程编程指南(2) 线程私有数据
概念及作用 在单线程程序中,我们经常要用到"全局变量"以实现多个函数间共享数据.在多线程环境下,由于数据空间是共享的,因此全局变量也为所有线程所共有.但有时应用程序设计中有必要提供 ...
- linux多线程学习笔记六--一次性初始化和线程私有数据【转】
转自:http://blog.csdn.net/kkxgx/article/details/7513278 版权声明:本文为博主原创文章,未经博主允许不得转载. 一,一次性初始化 以保证线程在调用资源 ...
- 【C/C++多线程编程之十】pthread线程私有数据
多线程编程之线程私有数据 Pthread是 POSIX threads 的简称.是POSIX的线程标准. 线程同步从相互排斥量[C/C++多线程编程之六]pthread相互排 ...
- pthread线程私有数据
进程内所有的线程共享地址空间,任何声明为静态或外部的变量,或在进程堆声明的变量都可以被进程内的所有线程读写. static,extern,或堆变量的值是上次线程改写的值 一个线程真正拥有的唯一私有存储 ...
- pthread_getspecific()--读线程私有数据|pthread_setspecific()--写线程私有数据
原型: #include <pthread.h> void *pthread_getspecific(pthread_key_t key); int pthread_setspecific ...
- Linux系统编程——线程私有数据
在多线程程序中.常常要用全局变量来实现多个函数间的数据共享.因为数据空间是共享的,因此全局变量也为全部线程共同拥有. 測试代码例如以下: #include <stdio.h> #inclu ...
- ZT linux 线程私有数据之 一键多值技术
这个原作者的这个地方写错了 且他举的例子非常不好.最后有我的修正版本 pthread_setspecific(key, (void *)&my_errno); linux 线程私有数据之一键多 ...
- Thread-specific data(TSD)线程私有数据
Thread-specific data(TSD)线程私有数据 http://blog.chinaunix.net/uid-26885237-id-3209913.html linux多线程编程中引入 ...
- 线程私有数据TSD——一键多值技术,线程同步中的互斥锁和条件变量
一:线程私有数据: 线程是轻量级进程,进程在fork()之后,子进程不继承父进程的锁和警告,别的基本上都会继承,而vfork()与fork()不同的地方在于vfork()之后的进程会共享父进程的地址空 ...
随机推荐
- TQ2440之定时器中断0——volatile关键字的重要作用
近日,在学习<ARM处理器裸机开发实战--机制而非策略>一书,在TQ2440开发板上,按照书中实例以及光盘配套程序源代码进行Timer0中断试验,编译成功后烧写到开发板上,没有任何反应,反 ...
- Java面试处理高并发
经过查资料,方案如下所示. 1 从最基础的地方做起,优化我们写的代码,减少必要的资源浪费. a.避免频繁的使用new对象,对于整个应用只需要存在一个实例的类,我们可以使用单例模 ...
- Websocket——Websocket原理
偶然在知乎上看到一篇回帖,瞬间认为之前看的那么多资料都不及这一篇回帖让我对 websocket 的认识深刻有木有.所以转到我博客里,分享一下.比較喜欢看这样的博客,读起来非常轻松.不枯燥,没有布道师的 ...
- Ubuntu12.04+OpenERP7.0安装笔记
不经意的一次看到OpenERP这个开源ERP,就被其丰富的功能,简洁的画面,熟悉的语言所吸引.迫不及待的多方查询资料,自己架设一个测试环境来进行了解.以下为测试安装时候的步骤说明,以备查询,并供有需要 ...
- mysql 运行计划explain具体解释
explain主要是用来获取一个query的运行计划,描写叙述mysql怎样运行查询操作.运行顺序,使用到的索引,以及mysql成功返回结果集须要运行的行数.能够帮助我们分析 select 语句,让我 ...
- 〖Linux〗Qt+gsoap开发客户端程序,服务端地址设定的字符串转换处理
之所以写出来,是由于经常因为这个问题屡屡丢面子.. 一般情况下,QString转换成(char*),我们一般直接使用: char *str = qstr->text().toLatin1().d ...
- global语句(python学习手册422页)
# -*- coding: cp936 -*- #python 27 #xiaodeng #global语句(python学习手册422页) #实际上就是一个名为__builtin__的模块,但是必须 ...
- Exception in thread main java.lang.NoClassDefFoundError: org/apache/juli/logging/LogFacto
报错: Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/juli/logging/Log ...
- HDUOJ----专题训练C
Problem C Time Limit : 1000/1000ms (Java/Other) Memory Limit : 32768/32768K (Java/Other) Total Sub ...
- tkinter Canvas画图片大坑总结
一.ImportError: cannot import name '_imagingtk' 问题描述 使用tkinter画pillow生成的图片时,在tkinter中抛出此异常. 解决方案 pip ...