线程的私有数据

在多线程程序中,经常要用全局变量来实现多个函数间的数据共享。由于数据空间是共享的,因此全局变量也为所有线程共有。但有时应用程序设计中必要提供线程私有的全局变量,这个变量仅在线程中有效,但却可以跨过多个函数访问。比如在程序里可能需要每个线程维护一个链表,而会使用相同的函数来操作这个链表,最简单的方法就是使用同名而不同变量地址的线程相关数据结构。这样的数据结构可以由 Posix 线程库维护,成为线程私有数据 (Thread-specific Data,或称为 TSD)。

#include <pthread.h>
/* 创建一个类型为 pthread_key_t 类型的私有数据变量( key )。 */
int pthread_key_create(pthread_key_t *key, void (*destructor)(void*));
/* 参数:
    key:在分配( malloc )线程私有数据之前,需要创建和线程私有数据相关联的键( key ),这个键的功能是获得对线程私有数据的访问权。
    destructor:清理函数名字( 如:fun )。当线程退出时,如果线程私有数据地址不是非 NULL,此函数会自动被调用。该函数指针可以设成 NULL ,这样系统将调用默认的清理函数。
        回调清理函数其定义如下:
        void fun(void *arg)
        {
            // arg 为 key 值
        }
*/

/* 返回值:
    成功:0
    失败:非 0
*/

#include <pthread.h>

/* 注销线程私有数据。这个函数并不会检查当前是否有线程正使用线程私有数据( key ),也不会调用清理函数 destructor() ,而只是将线程私有数据( key )释放以供下一次调用 pthread_key_create() 使用。 */
int pthread_key_delete(pthread_key_t key);

/* 参数:
    key:待注销的私有数据。
*/

/* 返回值:
    成功:0
    失败:非 0
*/
#include <pthread.h>

/* 设置线程私有数据( key ) 和 value 关联,注意,是 value 的值(不是所指的内容)和 key 相关联。 */
int pthread_setspecific(pthread_key_t key, const void *value);

/* 参数:
    key:线程私有数据。
    value:和 key 相关联的指针。
*/

/* 返回值:
    成功:0
    失败:非 0
*/
#include <pthread.h>

/* 读取线程私有数据( key )所关联的值。 */
void *pthread_getspecific(pthread_key_t key);

/* 参数:
    key:线程私有数据。
*/

/* 返回值:
    成功:线程私有数据( key )所关联的值。
    失败:NULL
*/

代码

#include<pthread.h>
#include<stdio.h>
#include<unistd.h>

pthread_key_t key;

/* 公用函数 */
void print(pthread_t pthrd)
{
    /* 不同的线程可以通过同一个 key 值访问各自的私有数据 */
    printf("I am %lu, value=%d\n",pthrd,*((int*)pthread_getspecific(key)));
    int value = *((int*)pthread_getspecific(key));
}

/* 创建的第一个线程的回调函数 */
static void* start_pthread1(void* arg)
{
    pthread_t pthrd = pthread_self();
    int value = 0;
    /* 将 value 关联 key 值 */
    pthread_setspecific(key,(const void*)&value);
    for (int i = 0; i < 5; i++)
    {
        print(pthrd);
        sleep(1);
    }    
    return NULL;
}

/* 创建的第二个线程的回调函数 */
static void* start_pthread2(void* arg)
{
    pthread_t pthrd = pthread_self();
    int value = 5;
    /* 将 value 关联 key 值 */
    pthread_setspecific(key,(const void*)&value);
    for (int i = 0; i < 5; i++)
    {
        print(pthrd);
        sleep(1);
    }    
    return NULL;
}

int main()
{
    pthread_t thread1;
    pthread_t thread2;
    
    /* 创建私有数据 */
    pthread_key_create(&key,NULL);

    /* 创建线程 */
    pthread_create(&thread1,NULL,start_pthread1,(void*)("number one"));
    pthread_create(&thread2,NULL,start_pthread2,(void*)("number two"));

    /* 等待线程结束,回收资源 */
    pthread_join(thread1,NULL);
    pthread_join(thread2,NULL);

    /* 删除私有数据 */
    pthread_key_delete(key);

    return 0;
}

执行可见,在不同线程里,key 关联这不同的数据,此时这些数据就是线程私有的。

 lingyun@manjaro  ~/Document/CppCode/study  gcc study.cpp -o study -lpthread -g
 lingyun@manjaro  ~/Document/CppCode/study  ./study                            
I am 140440438978304, value=0
I am 140440430585600, value=5
I am 140440430585600, value=5
I am 140440438978304, value=0
I am 140440430585600, value=5
I am 140440438978304, value=0
I am 140440438978304, value=0
I am 140440430585600, value=5
I am 140440438978304, value=0
I am 140440430585600, value=5
 lingyun@manjaro  ~/Document/CppCode/study  

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值