概述
线程特定数据(线程私有数据)是存储和查询某个特定线程相关数据的一种机制,使用这种机制是因为我们希望每个线程可以访问它自己单独的数据副本,而不需要担心与其他线程的访问同步问题。
线程的好处就在于促进了进程中数据和属性的共享,那么设计线程私有数据的用意是什么呢?有如下两点原因:
- 有时候需要维护基于每个线程的数据,而建立一个全局数组并通过线程号作为索引这种方式并不方便,并且对数组的访问无法受到保护。
- 提供了让基于进程的接口适应多线程环境的机制。例如errno,每个线程都有一个私有的errno值,在一个线程中对errno进行修改不会改变它在其它线程中的值。
我们知道一个进程中的每个线程都能够访问该进程的整个地址空间。除非使用寄存器,一个线程没有办法阻止另一个线程访问它的数据,虽然在底层实现上无法阻止这种访问,但是管理线程特定数据的函数可以加强线程间数据的独立性。
再分配特定数据之前,需要创建与该数据关联的键,这个键用于获取对线程特定数据的访问。键的数据类型:pthread_key_t
创建函数:
int pthread_key_create(pthred_key_t *keyp, void (*destructor) (void *));
创建的键存储在keyp所指内存单元中,这个键可以被进程中的所有线程使用,每个进程把这个键与不同的数据相关联。
创建时可以为该键关联一个析构函数,线程退出时,若数据地址非空,这个函数会被调用。由于线程常使用malloc为线程特定数据分配内存,所以为防止内存泄漏,要在析构函数中释放数据的内存。注意一个线程特定数据可以关联多个键,每个键可以绑定不同的析构函数。线程退出时,这些析构函数会被依次调用。
关联函数:
int pthread_setspecific(pthread_key_t key, const void *val);
void *pthread_getspecific(pthread_key_t key);
pthread_setspecific将键与特定数据的地址相关联,通过pthread_setspecific则可以获取与键相关联的数据的地址,如果没有数据和键相关联,则返回NULL。
取消关联函数:
int pthread_key_delete(pthread_key_t key);
该函数用于取消键和数据的关联,但是调用该函数并不会激活析构函数。