pthread_join是如何实现的?

发布于 2024-08-31 23:18:30 字数 476 浏览 6 评论 0原文

我对线程有点陌生,所以你必须原谅这个问题的天真。

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
    }
}

这是一个准确的描述,还是我大大过度简化了过程?

干杯!

I'm a little new to threading, so you'll have to forgive the naiveté of this question.

How is pthread_join implemented and how does it effect thread scheduling?

I always pictured pthread_join implemented with a while loop, simply causing the calling thread to yield until the target thread completes. Like this (very approximate pseudocode):


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
    }
}

Is this an accurate depiction, or am I vastly oversimplifying the process?

Cheers!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

拥抱我好吗 2024-09-07 23:18:30

pthread_join 可能在内部实现为等待信号量,该信号量在线程退出时触发,无论是在调用 pthread_exit 时还是在其 main 函数退出时。

无论如何,glibc的源代码是可用的,尝试谷歌代码搜索(我在那里看到了一些信息丰富的东西)

pthread_join is probably internally implemented as a wait for a semaphore which is triggered when the thread exits, either when it calls pthread_exit or when its main function exits.

In any case, the source code for glibc is available, try google code search (I saw some informative stuff in there)

别想她 2024-09-07 23:18:30

是的,这就是总体思路。有关特定实现的详细信息,请查看 glibc

Yes that's the general idea. For gory details of a particular implementation take a look at glibc.

世界和平 2024-09-07 23:18:30

线程通常有一个与其关联的小结构,即线程上下文。该结构可以填充使线程“工作”所需的所有数据。

例如,数据结构的根需要访问该线程的线程特定键,并在线程关闭时迭代它们以清理它们。

该结构中通常有一个类似互斥锁的锁,并且对于不同的部分可能有多个锁。

线程上下文中可以有一个小字段,终止线程可以在其中放置其退出状态。 (由 pthread_exit 返回或从线程函数返回的 void *。)

线程上下文还可以指示线程的状态(尚未创建、正在运行、已停止)。

在准备好终止状态并指示它正在终止之后,线程可以同步原语,例如条件变量或信号量。

pthread_join 函数可以等待该同步原语。一旦等待完成,除了提取状态之外,该函数还可以触发该线程的资源清理。

发出加入信号后,线程继续执行。为此,它必须继续拥有带有堆栈的上下文。之后,系统必须解决在后台彻底停止线程的问题。

线程的用户空间实现可以将其推迟到内核。例如,某些信号可能会消失或指示线程已完成的任何信号。此时,用户空间知道线程不可能再使用其堆栈,并且可以回收它。

在内核中,调度程序可以“吃掉”一个线程。线程可以调用调度程序中的某些函数,这些函数在清理其大部分资源后永远不会返回。它将线程标记为死亡并将上下文切换到另一个线程。线程的堆栈将永远不会再次使用(因为该函数永远不会返回)并且可以回收,以及它的任务结构和附加到它的任何剩余内容。

A thread typically has a little structure associated with it, the thread context. That structure can be stuffed with all the pieces of data which are needed to make the thread "work".

For instance, the root of a data structure needed to access the thread-specific keys of that thread, and to iterate over them to clean them up when it is being shut down.

There is typically a mutex-like lock in that structure, and perhaps more than one for different sections.

The thread context can have a little field in it where a terminating thread can place its exit status. (The void * returned by pthread_exit or by returning from the thread function.)

The thread context can also indicate the thread's state (not yet created, running, stopped).

There may be a synchronization primitive, such as a condition variable or semaphore, which the thread can kick, after preparing the termination status and indicating that it is terminating.

The pthread_join function can wait on that synchronization primitive. Once the wait finishes, the function can trigger a resource clean up for that thread, in addition to pulling out the status.

The thread continues to execute after signaling the join. To do that it must continue to have a context with a stack. After that point, the system has to work out the problem of cleanly stopping the thread in the background.

A user-space implementation of threading can defer that to the kernel. E.g. some signal can go off or whatever indicating that a thread has finished. At that point, user space knows that the thread cannot possibly be using its stack any more and can recycle it.

In the kernel, the scheduler can "eat" a thread. The thread can call some function in the scheduler which never returns after cleaning up most of its resources. It marks the thread as dead and switches context to another thread. The thread's stack will never be used again (since that function never returns) and can be reclaimed, as well as its task structure and any remaining things attached to it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文