Linux 多任务编程——线程私有数据

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

 

测试代码如下:

  1. #include <stdio.h>

  2. #include <pthread.h>

  3. #include <unistd.h>

  4. #include <stdlib.h>

  5.  
  6. int key = 100; //全局变量

  7.  
  8. void *helloworld_one(void *arg)

  9. {

  10. printf("the message is %s\n",(char *)arg);

  11. key = 10;

  12. printf("key=%d, the child id is %lu\n", key, pthread_self());

  13.  
  14. return NULL;

  15. }

  16.  
  17. void *helloworld_two(void *arg)

  18. {

  19. printf("the message is %s\n", (char *)arg);

  20. sleep(1);

  21. printf("key=%d, the child id is %lu\n", key, pthread_self());

  22.  
  23. return NULL;

  24. }

  25.  
  26. int main(int argc, char *argv[])

  27. {

  28. pthread_t thread_id_one;

  29. pthread_t thread_id_two;

  30.  
  31. //创建线程

  32. pthread_create(&thread_id_one, NULL, helloworld_one, "helloworld_one");

  33. pthread_create(&thread_id_two, NULL, helloworld_two, "helloworld_two");

  34.  
  35. //等待线程结束,回收资源

  36. pthread_join(thread_id_one, NULL);

  37. pthread_join(thread_id_two, NULL);

  38.  
  39. return 0;

  40. }


运行结果如下:

 

由运行结果可以看出,其中一个线程对全局变量的修改将影响到另一个线程的访问。

 

但有时应用程序设计中必要提供线程私有的全局变量,这个变量仅在线程中有效,但却可以跨过多个函数访问。比如在程序里可能需要每个线程维护一个链表,而会使用相同的函数来操作这个链表,最简单的方法就是使用同名而不同变量地址的线程相关数据结构。这样的数据结构可以由 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

 

示例代码如下:

  1. // this is the test code for pthread_key

  2. #include <stdio.h>

  3. #include <pthread.h>

  4.  
  5. pthread_key_t key; // 私有数据,全局变量

  6.  
  7. void echomsg(void *t)

  8. {

  9. printf("[destructor] thread_id = %lu, param = %p\n", pthread_self(), t);

  10. }

  11.  
  12. void *child1(void *arg)

  13. {

  14. int i = 10;

  15.  
  16. pthread_t tid = pthread_self(); //线程号

  17. printf("\nset key value %d in thread %lu\n", i, tid);

  18.  
  19. pthread_setspecific(key, &i); // 设置私有数据

  20.  
  21. printf("thread one sleep 2 until thread two finish\n\n");

  22. sleep(2);

  23. printf("\nthread %lu returns %d, add is %p\n",

  24. tid, *((int *)pthread_getspecific(key)), pthread_getspecific(key) );

  25. }

  26.  
  27. void *child2(void *arg)

  28. {

  29. int temp = 20;

  30.  
  31. pthread_t tid = pthread_self(); //线程号

  32. printf("\nset key value %d in thread %lu\n", temp, tid);

  33.  
  34. pthread_setspecific(key, &temp); //设置私有数据

  35.  
  36. sleep(1);

  37. printf("thread %lu returns %d, add is %p\n",

  38. tid, *((int *)pthread_getspecific(key)), pthread_getspecific(key));

  39. }

  40.  
  41. int main(void)

  42. {

  43. pthread_t tid1,tid2;

  44. pthread_key_create(&key, echomsg); // 创建

  45.  
  46. pthread_create(&tid1, NULL, child1, NULL);

  47. pthread_create(&tid2, NULL, child2, NULL);

  48. pthread_join(tid1, NULL);

  49. pthread_join(tid2, NULL);

  50.  
  51. pthread_key_delete(key); // 注销

  52.  
  53. return 0;

  54. }


运行结果如下:

 

 

从运行结果来看,各线程对自己的私有数据操作互不影响。也就是说,虽然 key 是同名且全局,但访问的内存空间并不是同一个。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值