谈谈多线程编程的个人理解(数据私有变量)

本文介绍了如何在多线程编程中使用线程私有数据,包括pthread_key_create函数创建线程私有数据,以及线程资源回收时的释放处理。线程私有数据通过TSD池和线程描述结构中的二维数组实现,确保各线程间互不干扰。示例代码展示了如何设置和获取线程私有数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

1、尽管加了头文件pthread.h,但多线程库不在系统库了,故需要手动添加参数,即-lpthread把库libpthread.a加进去编译。

2、线程私有数据
利用pthread_key_create(pthread_key *key, void (*destr_function)(void *))创建线程私有数据,即对各个线程都可见。其原理如下:
POSIX线程库维护TSD池,具体为一个结构数组,即
static struct pthread_key_struct pthread_keys[PTHREAD_KEYS_MAX]={{0, NULL}};
pthread_key_struct结构体中有两项:int in_use或0;destructor函数
当利用函数创建一个线程私有数据时,该函数在TSD池中分配一项,也就是将该结构数组中的某一项的成员一设置为in_use,设置destructor函数为destr_function。并吧该数组的索引值返回给*key,这样通过*key便可以查找该数组并做后继的删除TSD处理,还有线程结束时调用释放函数。
各个线程都有一个二维数组,位于线程描述结构里。用来存放与key关联的值。
#define PTHREAD_KEY_2NDLEVEL_SIZE 32
#define PTHREAD_KEY_1STLEVEL_SIZE \
((PTHREAD_KEYS_MAX + PTHREAD_KEY_2NDLEVEL_SIZE - 1)/PTHREAD_KEY_2NDLEVEL_SIZE)
这样,跟某个key关联的值会存放到稀疏矩阵中某个特定的位置。位置由如下公式决定:
idx1st = key/PTHREAD_KEY_2NDLEVEL_SIZE
idx2nd = key%PTHREAD_KEY_2NDLEVEL_SIZE
读取某个跟key关联的值也是利用此公式找到索引位置,然后读出数据。
这样,对于同一个线程来说,不同的线程私有数据,对应TDS池中不同的项,也就是结构数组中不同的项,也就是对应不同的结构数组索引值(存放于key中)。而与不同key关联的值也会存放于该线程描述结构里的二维数组的不同位置。一个key对应一个固定位置。而对于不同线程来说,虽然key值相同,都对应于结构数组的某一项,但与key关联的值读写是对线程各自线程描述结构里的二维数组相应位置进行读写,所以相互互不干扰。
由此可以看出,线程私有数据key对各个线程来说是可见的,但各个线程对其读写是互不干扰的。
当注销线程私有数据时,线程私有数据注销函数并不检查是否有线程正在使用这个TSD,也不会调用清理函数,而只是释放TSD以供下一次调用线程私有数据注册函数时使用,具体为把结构数组里的某一项的成员设置为0和NULL。
当线程结束时,会在线程资源(如线程描述结构)被回收前决定是否调用释放函数。如果该线程私有数据有关联值,则会以线程私有数据为参数调用该释放函数(实际是线程私有数据关联值)。如果没有关联值则不会调用释放函数。

注销线程私有数据int pthread_key_delete(pthread_key_t key)
访问TSD读写函数:
int pthread_setspecific(pthread_key_t key, const void *pointer)
void *pthread_getspecific(pthread_key_t key)

例程:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
pthread_key_t key;

void echomsg(void *t)
{
 printf("destructor excuted in thread %d, param=%d\n", pthread_self(), *(int *)t);
}

void *child1(void *arg)
{
 int tid = pthread_self();
 printf("thread %d enter\n", tid);
 pthread_setspecific(key, (void *)tid);
 sleep(2);
 printf("thread %d returns %d\n", tid, pthread_getspecific(key));
 sleep(5);
}

void *child2(void *arg)
{
 int tid = pthread_self();
 printf("thread %d enter\n", tid);
 pthread_setspecific(key, (void *)tid);
 sleep(1);
 printf("thread %d returns %d\n", tid, pthread_getspecific(key));
 sleep(5);
}

int main(void)
{
 pthread_t tid1, tid2;
 printf("hello\n");
 pthread_key_create(&key, echomsg);
 pthread_create(&tid1, NULL, child1, NULL);
 pthread_create(&tid2, NULL, child2, NULL);
 sleep(10);
 pthread_key_delete(key);
 printf("main thread exit\n");
 return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值