我不确定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(简单方式)实现的一些解释将不胜感激!
你的推理是正确的.这些调用用于特定于线程的数据.它们是一种为每个线程提供一个"全局"区域的方式,它可以存储它所需要的东西,但只有在需要它时才能存储它.
密钥在所有线程之间共享,因为它是在pthread_once()
第一次需要时创建的,但是为每个线程赋予该键的值是不同的(除非它保持设置为NULL).通过将值a void*
赋予内存块,需要线程特定数据的线程可以分配它并保存地址供以后使用.并且不调用需要特定于线程的数据的例程的线程永远不会浪费内存,因为它永远不会为它们分配.
我使用它们的一个方面是使标准C库是线程安全的.在我参与的一个实现中,strtok()
函数(与strtok_r()
我们这样做时被认为是令人憎恶的线程安全相反)在第一次调用它时使用了几乎完全相同的代码,分配了一些将由strtok()
用于存储后续呼叫的信息.这些后续调用将检索特定于线程的数据以继续对字符串进行标记,而不会干扰执行完全相同操作的其他线程.
这意味着库的用户不必担心线程之间的串扰 - 他们仍然必须确保单个线程在最后一个线程完成之前不调用该函数,但这与单线程代码相同.
它允许我们为我们系统中运行的每个线程提供一个"适当的"C环境,而不需要通常的"你必须调用这些特殊的非标准重入例程"限制,这是其他供应商对其用户施加的限制.
至于实现,从我记得的DCE用户模式线程(我认为是当前pthreads的前身),每个线程都有一个结构,存储指令指针,堆栈指针,寄存器内容等内容.向该结构添加一个指针以实现非常强大的功能并且成本最低是一件非常简单的事情.指针指向键/指针对的数组(在一些实现中的链表),因此每个线程可以具有多个键(例如,一个用于strtok()
,一个用于rand()
).