linux多线程应用--线程内部私有的全局变量(转载)
2009-09-19 23:26
267 查看
原文地址:http://hi.baidu.com/snowlxm/blog/item/9c52f95940f8c6232934f033.html
在单线程的程序里,有两种基本的数据:全局变量和局部变量。但在多线程程序里,还有第三种数据类型:线程数据(TSD: Thread-Specific Data)。它和全局变量很象,在线程内部,各个函数可以象使用全局变量一样调用它,但它对线程外部的其它线程是不可见的。这种数据的必要性是显而易见 的。例如我们常见的变量errno,它返回标准的出错信息。它显然不能是一个局部变量,几乎每个函数都应该可以调用它;但它又不能是一个全局变量,否则在 A线程里输出的很可能是B线程的出错信息。要实现诸如此类的变量,我们就必须使用线程数据。我们为每个线程数据创建一个键,它和这个键相关联,在各个线程 里,都使用这个键来指代线程数据,但在不同的线程里,这个键代表的数据是不同的,在同一个线程里,它代表同样的数据内容。
下面的多线程程序在Red Hat9上的测试通过的线程私有的全局变量使用的例子。为了简便起见,省去了所有的错误处理代码。其中的变量no是线程私有变量,就相当于线程内部的全局变量,可以看到,对no的访问不 能通过no本身变量去访问,而是通过一个全局变量key间接的去访问。从程序运行时的输出可以发现:线程可以在任何函数中访问no;线程拥有各自的no存 储空间。
#include<pthread.h>;
#include<stdio.h>;
pthread_key_t key;
void start();
void work();
int main()
{
pthread_t tid1,tid2;
pthread_key_create( &key, NULL );
pthread_create( &tid1,NULL,(void *)start,NULL );
pthread_create( &tid2,NULL,(void *)start,NULL );
pthread_join( tid1,NULL );
pthread_join( tid2,NULL );
pthread_key_delete( key );
}
void start()
{
int no;
pthread_setspecific( key, &no );
work();
}
void work()
{
int *p_no,i;
for( i=0;i<20;i++ ){
p_no = pthread_getspecific( key );
printf( "%d:%d/n", pthread_self(), *p_no );
*p_no = *p_no+1;
pthread_setspecific( key, p_no );
sleep(1);
}
}
说明:
(1)
线程1, 2共用了key,
通过key,就可以存取只跟当前线程相关的一个值(这个值由编译器管理)
线程1----->key----->线程1相关的值(由编译器管理)
线程2----->key----->线程2相关的值(由编译器管理)
设置"线程相关的数据",使用
int pthread_setspecific(pthread_key_t key, const void *pointer);
读取"线程相关的数据",使用
void * pthread_getspecific(pthread_key_t key);
注意到,这两个函数分别有一个void类型的指针,我们的线程就是通过这两个指针分别与
"线程相关的数据"的数据进行交互的
(2)
由于key是一个全局变量,
函数work不需要额外的参数就可以访问它;
又因为它是"线程相关的数据", 线程1, 2通过key存取的数据是相互独立的,
这样就不需要额外的互斥机制来保证数据访问的正确性了.
在单线程的程序里,有两种基本的数据:全局变量和局部变量。但在多线程程序里,还有第三种数据类型:线程数据(TSD: Thread-Specific Data)。它和全局变量很象,在线程内部,各个函数可以象使用全局变量一样调用它,但它对线程外部的其它线程是不可见的。这种数据的必要性是显而易见 的。例如我们常见的变量errno,它返回标准的出错信息。它显然不能是一个局部变量,几乎每个函数都应该可以调用它;但它又不能是一个全局变量,否则在 A线程里输出的很可能是B线程的出错信息。要实现诸如此类的变量,我们就必须使用线程数据。我们为每个线程数据创建一个键,它和这个键相关联,在各个线程 里,都使用这个键来指代线程数据,但在不同的线程里,这个键代表的数据是不同的,在同一个线程里,它代表同样的数据内容。
下面的多线程程序在Red Hat9上的测试通过的线程私有的全局变量使用的例子。为了简便起见,省去了所有的错误处理代码。其中的变量no是线程私有变量,就相当于线程内部的全局变量,可以看到,对no的访问不 能通过no本身变量去访问,而是通过一个全局变量key间接的去访问。从程序运行时的输出可以发现:线程可以在任何函数中访问no;线程拥有各自的no存 储空间。
#include<pthread.h>;
#include<stdio.h>;
pthread_key_t key;
void start();
void work();
int main()
{
pthread_t tid1,tid2;
pthread_key_create( &key, NULL );
pthread_create( &tid1,NULL,(void *)start,NULL );
pthread_create( &tid2,NULL,(void *)start,NULL );
pthread_join( tid1,NULL );
pthread_join( tid2,NULL );
pthread_key_delete( key );
}
void start()
{
int no;
pthread_setspecific( key, &no );
work();
}
void work()
{
int *p_no,i;
for( i=0;i<20;i++ ){
p_no = pthread_getspecific( key );
printf( "%d:%d/n", pthread_self(), *p_no );
*p_no = *p_no+1;
pthread_setspecific( key, p_no );
sleep(1);
}
}
说明:
(1)
线程1, 2共用了key,
通过key,就可以存取只跟当前线程相关的一个值(这个值由编译器管理)
线程1----->key----->线程1相关的值(由编译器管理)
线程2----->key----->线程2相关的值(由编译器管理)
设置"线程相关的数据",使用
int pthread_setspecific(pthread_key_t key, const void *pointer);
读取"线程相关的数据",使用
void * pthread_getspecific(pthread_key_t key);
注意到,这两个函数分别有一个void类型的指针,我们的线程就是通过这两个指针分别与
"线程相关的数据"的数据进行交互的
(2)
由于key是一个全局变量,
函数work不需要额外的参数就可以访问它;
又因为它是"线程相关的数据", 线程1, 2通过key存取的数据是相互独立的,
这样就不需要额外的互斥机制来保证数据访问的正确性了.
相关文章推荐
- linux 多线程应用--线程内部私有的全局变量
- linux多线程应用--线程内部私有的全局变量
- java全局变量在线程中应用
- 转载:关于C语言头文件的应用问题,主要还是关于全局变量的定义和声明问题
- 线程共享全局变量和私有全局变量
- python线程的使用方法以及全局变量的应用
- 线程高级应用-心得3-线程范围内的共享变量以及应用场景及面试题案例分析
- Operating System-进程/线程内部通信-信号量、PV操作的实现和应用(解决哲学家进餐和生产者消费者问题)
- c++在类的内部访问全局变量
- python:线程的使用、线程共享全局变量、列表作为参数(全局变量)、避免全局变量被修改
- C#-WebForm-★内置对象简介★Request-获取请求对象、Response相应请求对象、Session全局变量(私有)、Cookie全局变量(私有)、Application全局公共变量、ViewState
- 全局变量、extern/static/const区别与联系(转载)
- JS全局变量VAR和THIS--在函数内部,加var是局部变量,不加是全局变量
- Operating System-进程/线程内部通信-信号量、PV操作的实现和应用(解决哲学家进餐和生产者消费者问题)
- ThreadLocal类 线程间共享变量的应用
- 线程间通信的定义及全局变量的方法
- 今天发现frame和iframe的name属性竟然是其内部页面的全局变量
- v8学习---使用内部字段给js添加全局变量
- 静态变量(内部、外部) 全局变量 差别
- Sql Server全局变量(转载)