• Thread-specific data(TSD)线程私有数据


    Thread-specific data(TSD)线程私有数据

    http://blog.chinaunix.net/uid-26885237-id-3209913.html  

    linux多线程编程中引入了Thread-Specific Data(线程相关的数据)的概念
    为什么需要"线程相关的数据"呢?怎样使用"线程相关的数据"呢?

    1. 为什么需要Thread-Specific Data "线程相关的数据"

    这里只介绍我个人认为的一个原因, 当然它还有许多其他用途,欢迎大家讨论

    例子:实现同时运行两个线程,对于每个线程,在该线程调用的每个函数中打印线程的名字,以及它正在调用的函数的名字.

    (下面的例子与实现只是为了说明问题,有些地方可能不妥)

    不使用"线程相关的数据"的两种实现方法:

    实现方法1. 通过传参数,不使用全局变量
     
    #include
    #include
    #define MAXLENGTH 20

    void another_func (const char * threadName)
    {
    printf ("%s is running in another_func ", threadName);
    }

    void * thread_func (void * args)
    {
    char threadName[MAXLENGTH];
    strncpy (threadName, (char *)args, MAXLENGTH-1);

    printf ("%s is running in thread_func ", threadName);
    another_func (threadName);

    }

    int main (int argc, char * argv[])
    {

    pthread_t pa, pb;
    pthread_create ( &pa, NULL, thread_func, "Thread A");
    pthread_create ( &pb, NULL, thread_func, "Thread B");

    pthread_join (pa, NULL);
    pthread_join (pb, NULL);
    }

    输出结果为:
    Thread A is running in thread_func
    Thread A is running in another_func
    Thread B is running in thread_func
    Thread B is running in another_func

    该方法的缺点是:由于要记录是哪一个线程在调用函数,每个函数需要一个额外的参数来
    记录线程的名字,例如another_func函数需要一个threadName参数
    如果调用的函数多了,则每一个都需要一个这样的参数

    实现方法2. 使用全局变量,通过互斥
     
    #include
    #include
    #define MAXLENGTH 20

    char threadName[MAXLENGTH];
    pthread_mutex_t sharedMutex=PTHREAD_MUTEX_INITIALIZER;

    void another_func ()
    {
    printf ("%s is running in another_func ", threadName);
    }

    void * thread_func (void * args)
    {
    pthread_mutex_lock(&sharedMutex);
    strncpy (threadName, (char *)args, MAXLENGTH-1);
    printf ("%s is running in thread_func ", threadName);
    another_func ();
    pthread_mutex_unlock(&sharedMutex);

    }

    int main (int argc, char * argv[])
    {

    pthread_t pa, pb;
    pthread_create ( &pa, NULL, thread_func, "Thread A");
    pthread_create ( &pb, NULL, thread_func, "Thread B");

    pthread_join (pa, NULL);
    pthread_join (pb, NULL);
    }

    该方法的缺点是:由于多个线程需要读写全局变量threadName,就需要使用互斥机制

    分析以上两种实现方法,Thread-Specific Data "线程相关的数据"的一个好处就体现出来了:
    (1)"线程相关的数据"可以是一个全局变量,并且
    (2)每个线程存取的"线程相关的数据"是相互独立的.
     
    2. 怎样使用"线程相关的数据"

    这是利用"线程相关的数据"的实现方式:
     
    #include
    #include

    pthread_key_t p_key;

    void another_func ()
    {
    printf ("%s is running in another_func ", (char *)pthread_getspecific(p_key));//绑定私有数据之后,就可以使用pthread_getspecific进行私有数据访问了
    }

    void * thread_func (void * args)
    {
    pthread_setspecific(p_key, args);//在各线程中将私有数据与关键字进行绑定
    printf ("%s is running in thread_func ", (char *)pthread_getspecific(p_key));//绑定私有数据之后,就可以使用pthread_getspecific进行私有数据访问了
    another_func ();

    }

    int main (int argc, char * argv[])
    {

    pthread_t pa, pb;

    pthread_key_create(&p_key, NULL);//在主线程中创建关键字

    pthread_create ( &pa, NULL, thread_func, "Thread A");
    pthread_create ( &pb, NULL, thread_func, "Thread B");

    pthread_join (pa, NULL);
    pthread_join (pb, NULL);
    }

    说明:
    (1)
    线程A, B共用了p_key,
    通过p_key,就可以存取只跟当前线程相关的一个值(这个值由编译器管理)
    线程A----->p_key----->线程A相关的值(由编译器管理)
    线程B----->p_key----->线程B相关的值(由编译器管理)

    设置"线程相关的数据",使用
    int pthread_setspecific(pthread_key_t key, const void *pointer);
    读取"线程相关的数据",使用
    void * pthread_getspecific(pthread_key_t key);

    注意到,这两个函数分别有一个void类型的指针,我们的线程就是通过这两个指针分别与
    "线程相关的数据"的数据进行交互的

    (2)
    由于p_key是一个全局变量,
    函数another_func不需要额外的参数就可以访问它;
    又因为它是"线程相关的数据", 线程A, B通过p_key存取的数据是相互独立的,
    这样就不需要额外的互斥机制来保证数据访问的正确性了

    ================== End

  • 相关阅读:
    poj 1840(五元三次方程组)
    Selenium(二)开发环境的搭建
    Selenium(一)自动化测试简介
    (二)AppScan使用教程
    (一)AppScan的安装及破解
    (一)python3.7的安装
    读完《大道至简》后的反思
    BZOJ3585: mex
    BZOJ3544: [ONTAK2010]Creative Accounting
    BZOJ3531: [Sdoi2014]旅行
  • 原文地址:https://www.cnblogs.com/lsgxeva/p/11777783.html
Copyright © 2020-2023  润新知