Pthread

来源:互联网 发布:手甲钩淘宝 编辑:程序博客网 时间:2024/06/18 17:50

Pthread - 线程特定数据(thread-specified data)

在 Pthread 中,线程特定数据(thread-specified data,以下简称 TSD)是绑定由pthread_key_create()函数创建的 key 的属于调用线程自身的数据。简单地说就是一个全局变量可以被多个线程访问,但是在每个线程中该全局变量指向由本线程设定的值,而且每个线程都可以通过该全局变量访问到本线程设定的值,彼此互不干扰。以下是操作 TSD 的函数:

   void *pthread_getspecific(pthread_key_t key);   int pthread_setspecific(pthread_key_t key, const void *value);   int pthread_key_create(pthread_key_t *key, void (*destructor)(void *));   int pthread_key_delete(pthread_key_t key);

以下为测试程序:

#include <unistd.h>#include <errno.h>#include <pthread.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#define NUM_THREADS 2#define ERROR(func, no) { \        fprintf(stderr, "%s: %s\n", func, strerror(no)); \        exit(EXIT_FAILURE); \    }pthread_key_t key_tsd;typedef struct tsd {    pthread_t tid; // thread ID    char *str; //} tsd_t;pthread_once_t once_control = PTHREAD_ONCE_INIT;void destory_routine(void* value) {    printf("destory ...\n");    free(value); //delete dynamic storage allocated to each TSD}void init_routine() {    int ret;    ret = pthread_key_create(&key_tsd, destory_routine);    if(ret) {        ERROR("pthread_key_create", ret);    }    printf("Thread-specified data key initialized\n");}void* thread_routine(void *arg) {    //key will be initialized twice    //pthread_once_t once_control = PTHREAD_ONCE_INIT;    pthread_once(&once_control, init_routine); // make sure initialization actually only run once     pthread_t tid = pthread_self();    tsd_t* val = (tsd_t*)malloc(sizeof(tsd_t));    val->tid = tid;    val->str = (char*)arg;    pthread_setspecific(key_tsd, val);    printf("Thread %#lx set thread-specific data: %p\n",                         (size_t)tid, val);    val = pthread_getspecific(key_tsd);    printf("Thread %#lx get thread-specific data: %s\n",                         (size_t)val->tid, val->str);    sleep(2);     val = pthread_getspecific(key_tsd);    printf("Thread %#lx get thread-specific data: %s\n",                         (size_t)val->tid, val->str);    pthread_exit(NULL);}int main(int argc, char** argv){    int ret, i;    pthread_t tid[NUM_THREADS];    pthread_attr_t attr;    pthread_attr_init(&attr);    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);    if((ret=pthread_create(&tid[0], &attr, thread_routine, "Thread 1"))){            ERROR("pthread_create", ret);    }    if((ret=pthread_create(&tid[1], &attr, thread_routine, "Thread 2"))){            ERROR("pthread_create", ret);    }    pthread_attr_destroy(&attr);    for(i=0; i<NUM_THREADS; ++i) {        ret = pthread_join(tid[i], NULL);        if(ret) {            ERROR("pthread_join", ret);        }    }    pthread_key_delete(key_tsd);    exit(EXIT_SUCCESS);}

运行效果:
这里写图片描述

从程序的运行结果可以看出:两线程通过相同的可以访问到本线程的特定数据,并且程序中特意 sleep 一段时间后再次访问 TSD 结果不变,进一步验证 TSD 的特性。值得注意的是上述程序中调用了 pthread_once 函数来创建 pthread_key_t
变量,程序的运行结果可以发现该 key 只被初始化了一次,这是通过设置 pthread_once 函数的 once_control 参数实现的,而且要注意该参数的生存周期应为整个程序的运行周期,也就是说该参数应是一个全局变量或静态局部变量。而 destroy_routine 调用了两次,释放了各自线程为 TSD分配的动态内存。
once_control为局部变量, key被初始化两次:
这里写图片描述

0 0
原创粉丝点击