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

xiaoxiao2021-02-27  430

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被初始化两次:

转载请注明原文地址: https://www.6miu.com/read-443.html

最新回复(0)