我对线程有点新意,所以你必须原谅这个问题的天真。
如何实现pthread_join
以及它如何影响线程调度?
我总是想象pthread_join
用while循环实现,只是让调用线程屈服,直到目标线程完成。像这样(非常近似的伪代码):
atomic bool done; thread_run { do_stuff(); done = true; } thread_join { while(!done) { thread_yield(); // basically, make the thread that calls "join" on // our thread yield until our thread completes } }
这是一个准确的描述,还是我过分简化过程?
干杯!
答案 0 :(得分:4)
pthread_join可能在内部实现为等待信号量的等待,当信号调用pthread_exit或其主函数退出时,该信号量将在线程退出时触发。
在任何情况下,glibc的源代码都可用,请尝试谷歌代码搜索(我在那里看到了一些信息丰富的东西)
答案 1 :(得分:3)
是的,这是一般的想法。有关特定实现的血腥细节,请查看glibc。
答案 2 :(得分:1)
线程通常有一个与之关联的小结构,即线程上下文。该结构可以填充使线程“工作”所需的所有数据。
例如,数据结构的根需要访问该线程的特定于线程的密钥,并在它被关闭时迭代它们以清理它们。
在该结构中通常存在类似互斥锁的锁,并且对于不同的部分可能不止一个。
线程上下文中可以包含一个小字段,终止线程可以在其中放置其退出状态。 (由void *
返回的pthread_exit
或从线程函数返回。)
线程上下文还可以指示线程的状态(尚未创建,运行,停止)。
在准备终止状态并指示它正在终止之后,可能存在一个同步原语,例如条件变量或信号量,线程可以kick
。
pthread_join
函数可以等待该同步原语。等待完成后,除了拉出状态外,该函数还可以触发该线程的资源清理。
线程在发出连接信号后继续执行。要做到这一点,它必须继续具有堆栈的上下文。在那之后,系统必须解决在后台干净地停止线程的问题。
线程的用户空间实现可以将其推迟到内核。例如。某些信号可能会消失或表示线程已完成的任何信号。此时,用户空间知道线程不再可能正在使用其堆栈并且可以回收它。
在内核中,调度程序可以“吃掉”一个线程。线程可以调用调度程序中的某个函数,该函数在清理了大部分资源后永远不会返回。它将线程标记为死并将上下文切换到另一个线程。线程的堆栈永远不会再次使用(因为该函数永远不会返回)并且可以被回收,以及它的任务结构和附加到它的任何剩余内容。