您的位置:首页 > 其它

线程特定数据(学习)

2015-01-14 16:03 162 查看
1、首先,为什么要使用线程特定数据呢?什么是线程特定数据。这牵涉到重入函数和不可重入函数。

重入函数就是在多个进程或者线程中,可以同时进行运行的函数,可重入函数就是不可以同时运行的函数,这个主要是可能多个进程或线程共享了一个变量,这个变量只有一个,这样同时运行的时候,就会出问题了,因为我们不知道这个静态变量具体是存入的什么值,可能刚存入一个值,立马又因为调用这个函数编程另外一个值。更加通俗的说,

在函数体内不访问那些全局变量,不使用静态局部变量,坚持只使用局部变量,写出的函数就将是可重入的。如果必须访问全局变量,记住利用互斥信号量来保护全局变量。

好了,说了这么多,如果多个线程同时访问一个函数,而这个函数恰好也必须使用一个静态变量,那么,线程特定数据就是来解决这个问题的。

2、每一个系统支持的线程特定数据元素限制不一样。POSIX要求这个限制不小于128(每一格进程)。系统为每一个进程维护一个称之为Key结构的结构数组。如图1



Key结构中额标志指示这个数组元素是否正在使用。当一个线程调用进程创建函数pthread_key_create时候,系统搜索该进程的Key结构数组找到第一个不使用的的元素,该元素的索引称之为键,返回给调用线程的正是这个索引。

除了进程范围内的Key结构数组外,系统还在进程内维护关于每一个线程的多条信息。这些特定于线程的信息我们称之为Pthread结构,如图2



pthread结构与Key结构是一一对应的。当创建一个线程的时候,系统会根据Key结构搜索,得到一个返回值,也就是Key结构的索引,每一个线程可以为该键值存储一个值(指针)。这个指针通常是通过malloc获取的。如图3。这样,当一个函数有一个静态变量的时候,多个线程同时访问,因为这个静态变量存放在键值中,就不会存在一个线程将另外一个线程的值覆盖的情况了。



因为是malloc分配的实际数据空间,所以在线程结束的时候一定注意了,要释放空间。这个可以在析构函数中进行。

线程特定函数的典型用法如下:

[cpp] view
plaincopy

pthread_key_t r1_key;

pthread_once_t re_once = PTHREAD_ONCE_INIT;

//定义析构函数,释放空间

void readline_destructor(void *ptr)

{

free(ptr);

}

//初始化函数

void readline_once(void)

{

pthread_key_create(&r1_key,readline_destructor);

}

ssize_t

readline(...)

{

....

pthread_once(&r1_once,readline);

if((ptr = pthread_getspecific(r1_key)) == NULL)

{

ptr = malloc(....);

//设置键值对。

pthread_setspecific(r1_key,ptr);

....

}

.....

}

每一次readline被调用的时候,它都调用pthread_once,根据r1_once的值(PTHREAD_ONCE_INIT),readline这个函数值被调用了一次。pthread_getspecific()获取相应的特定线程数据,pthread_setspecific()设置特定线程数据。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: