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

測试代码例如以下:

#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

最新文章

  1. 数据库设计范式1&mdash;&mdash;三范式
  2. linux 平均负载 load average 的含义
  3. redis AND memcache
  4. input type=file
  5. LintCode &quot;Previous Permutation&quot;
  6. Web Api 2 用户认证模板解析-----外部用户认证模式
  7. CentOS6.5下docker的安装及遇到的问题和简单使用
  8. nest &#39;for&#39; loop.
  9. OOP编程特性综合项目
  10. 【HAOI2009】毛毛虫
  11. Linux 网卡Bond模式
  12. parson json解析
  13. mysql 导入时报错:Got a packet bigger than‘max_allowed_packet’bytes
  14. Spring Boot 教程demo
  15. 20155308 2016-2017-2 《Java程序设计》第8周学习总结
  16. 更改vim高亮括号匹配颜色
  17. java - 线程1打印1-10,当线程打印到5后,线程2打印“hello”,然后线程1继续打印
  18. Express重定向
  19. MB/s与Mbit/s的区别
  20. IE6,7,8支持css圆角

热门文章

  1. SpringMVC &amp;amp; Struts2
  2. LINUX下为apache 和 PHP 添加模块
  3. jquery--new返回值
  4. heap-adb shell查看堆栈使用
  5. actionbar-去掉背景的阴影
  6. TextView- 内容过长省略号设定
  7. 深入理解Java内存模型--转载
  8. 【arc062e】Building Cubes with AtCoDeer
  9. arukas 的 Endpoint
  10. ie为什么那么垃圾(不是ie垃圾,是ie用的人太多了,很多在用低版本)