zoukankan      html  css  js  c++  java
  • 线程私有数据

    在多线程程序中。常常要用全局变量来实现多个函数间的数据共享。

    因为数据空间是共享的。因此全局变量也为全部线程共同拥有。


    測试代码例如以下:

    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 ",(char *)arg);  
    11.     key = 10;  
    12.     printf("key=%d, the child id is %lu ", key, pthread_self());  
    13.       
    14.     return NULL;  
    15. }  
    16.   
    17. void *helloworld_two(void *arg)  
    18. {  
    19.     printf("the message is %s ", (char *)arg);  
    20.     sleep(1);  
    21.     printf("key=%d, the child id is %lu ", 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 ", pthread_self(), t);   
    10. }   
    11.   
    12. void *child1(void *arg)   
    13. {   
    14.     int i = 10;  
    15.       
    16.     pthread_t tid = pthread_self(); //线程号  
    17.     printf(" set key value %d in thread %lu ", i, tid);   
    18.       
    19.     pthread_setspecific(key, &i); // 设置私有数据  
    20.       
    21.     printf("thread one sleep 2 until thread two finish ");  
    22.     sleep(2);   
    23.     printf(" thread %lu returns %d, add is %p ",  
    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(" set key value %d in thread %lu ", temp, tid);   
    33.       
    34.     pthread_setspecific(key, &temp); //设置私有数据  
    35.       
    36.     sleep(1);   
    37.     printf("thread %lu returns %d, add is %p ",   
    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 是同名且全局,但訪问的内存空间并非同一个。


    本教程演示样例代码下载请点此处。


  • 相关阅读:
    msf提权命令/meterpreter下的几个命令
    ms17010漏洞复现-2003
    复现IIS6.0远程命令执行漏洞
    代码审计之Finecms任意文件下载漏洞
    逻辑运算符
    RIP动态路由的配置
    跟着百度学习php之ThinkPHP的运行流程-2
    静态路由配置
    跟着百度学习php之ThinkPHP的运行流程-1
    外挂是怎么写的?
  • 原文地址:https://www.cnblogs.com/zsychanpin/p/6902521.html
Copyright © 2011-2022 走看看