我不确定pthread数据特定的工作方式:考虑下一个代码(在网上找到),这是否意味着我可以在main中创建例如5个线程,只在其中一些中调用func(假设2)那些线程将数据'key'设置为某个(ptr = malloc(OBJECT_SIZE)),而其他线程将具有相同的密钥但是具有NULL值?
static pthread_key_t key;
static pthread_once_t key_once = PTHREAD_ONCE_INIT;
static void
make_key()
{
(void) pthread_key_create(&key, NULL);
}
func()
{
void *ptr;
(void) pthread_once(&key_once, make_key);
if ((ptr = pthread_getspecific(key)) == NULL) {
ptr = malloc(OBJECT_SIZE);
...
(void) pthread_setspecific(key, ptr);
}
...
}
关于数据特定如何工作以及如何以pthread(简单方式)实现它的一些解释将不胜感激!
答案 0 :(得分:6)
你的推理是正确的。这些调用用于特定于线程的数据。它们是一种给每个线程一个“全局”区域的方式,它可以存储它所需要的东西,但只有在它需要的时候才能存储。
密钥在所有线程之间共享,因为它是在第一次需要时使用pthread_once()
创建的,但是为每个线程赋予该键的值是不同的(除非它保持设置为NULL)。通过将值void*
添加到内存块,需要线程特定数据的线程可以分配它并保存地址供以后使用。并且不调用需要特定于线程的数据的例程的线程永远不会浪费内存,因为它永远不会为它们分配。
我使用它们的一个方面是使标准C库具有线程安全性。在我参与的实现中,strtok()
函数(与我们这样做时被认为是令人憎恶的线程安全strtok_r()
相对)在第一次调用时使用了几乎完全相同的代码,分配一些将由strtok()
用于存储后续调用信息的内存。这些后续调用将检索特定于线程的数据,以继续对字符串进行标记,而不会干扰执行完全相同操作的其他线程。
这意味着库的用户不必担心线程之间的串扰 - 他们仍然必须确保单个线程在最后一个线程完成之前没有调用该函数,但这与单个线程相同线程代码。
它允许我们为我们系统中运行的每个线程提供一个“适当的”C环境,而不需要通常的“你必须调用这些特殊的非标准重入例程”限制,这是其他供应商对其用户施加的限制。
至于实现,从我记得的DCE用户模式线程(我认为是当前pthreads的前身),每个线程都有一个结构,存储指令指针,堆栈指针,寄存器内容等等。上。向该结构添加一个指针以实现非常强大的功能并且成本最低是一件非常简单的事情。指针指向键/指针对的数组(在某些实现中的链表),因此每个线程可以有多个键(例如,一个用于strtok()
,一个用于rand()
)。
答案 1 :(得分:1)
你的第一个问题的答案是肯定的。简单来说,它允许每个线程分配和保存自己的数据。这大致等同于每个线程只分配和传递其自己的数据结构。 API为您节省了将线程局部结构传递给所有子功能的麻烦,并允许您根据需要进行查找。
只要结果相同,实现真的无关紧要(每个操作系统可能有所不同)。
您可以将其视为两级哈希映射。键指定要访问的线程本地“变量”,第二级可以执行线程ID查找以请求每线程值。