【问题标题】:Detached vs. Joinable POSIX threads分离与可连接 POSIX 线程
【发布时间】:2011-04-14 23:41:46
【问题描述】:

我一直在使用 pthread 库在 C 中创建和加入线程。

  1. 我什么时候应该从一开始就创建一个分离的线程?与可连接线程相比,它是否提供任何性能优势?

  2. 在可连接(默认)线程上不执行pthread_join() 是否合法?或者这样的线程应该总是在pthread_exit()ing之前使用detach()函数?

【问题讨论】:

    标签: c linux pthreads detach


    【解决方案1】:
    1. 当你知道你不想用pthread_join() 等待它时,创建一个分离的线程。唯一的性能优势是,当分离的线程终止时,可以立即释放其资源,而不必等待线程加入才能释放资源。

    2. 不加入可连接线程是“合法的”;但通常不建议这样做,因为(如前所述)在线程加入之前不会释放资源,因此如果您不加入,它们将无限期地保持绑定(直到程序退出)。

    【讨论】:

    • 疑问:在分离线程的情况下,如果主线程在分离线程完成之前完成执行怎么办?我认为这将终止杀死所有线程的进程。那么在什么情况下使用分离线程,因为我应该确保分离线程已经完成执行?
    • @Ajax:根据经验,如果主线程完成,则程序退出并且线程……终止。至少,这似乎是 Mac OS X (10.10.1 Yosemite) 上的行为。如果调用 exit()_exit()_Exit(),我在 POSIX 文档中找不到任何指示其他线程继续运行的内容。如果主线程执行pthread_exit(),那么其他线程确实有机会完成。
    • 另外一个说明:可分离线程适用于已经有其他轮询机制的情况;您可以使用相同的轮询机制来检查结果状态,从而知道线程是否完成。这是一个案例,“准备好了吗?如果准备好了,请使用它。”
    • 如果我忘记调用 pthread_join,我可以在它退出之前调用 pthread_detach 以避免内存泄漏吗?
    • @DareDevil:是的,但是……您应该分离线程,因为您不需要知道线程的返回状态,也不需要知道它已经完成,而不是因为您可能忘记加入它。并且一旦分离,就不能尝试加入线程。
    【解决方案2】:

    我什么时候应该从一开始就创建一个分离的线程?

    只要应用程序不关心线程何时完成并且也不关心线程的返回值(线程可以通过pthread_exit 将值传回给其他线程/应用程序)。

    例如,在客户端-服务器应用程序模型中,服务器可能会创建一个新线程来处理每个请求。但是服务器本身并不关心线程的线程返回值。在这种情况下,创建 detached 线程是有意义的。

    服务器唯一需要确保的是当前处理的请求已经完成。它可以这样做,只需退出主线程而不退出整个程序/应用程序。当进程中的最后一个线程退出时,应用程序/程序自然会退出。

    伪代码可能如下所示:

    /* A server application */
    
    void process(void *arg)
    {
        /* Detach self. */
        pthread_detach(pthread_self());
        
        /* process a client request. */
        
        pthread_exit(NULL);
    }
    
    int main(void)
    {
    
        while (not_done) {
            pthread_t t_id;
            errno = pthread_create(&t_id, NULL, process, NULL);
            if (errno) perror("pthread_create:");
        }
    
        /* There may be pending requests at this point. */
        
        /* Just exit the main thread - not the whole program - so that remaining
           requests that may still be processed can continue. */
        pthread_exit(NULL);
    }
    

    另一个示例可能是守护程序或记录器线程,只要应用程序运行,它就会定期记录一些信息。

    与可连接线程相比,它是否提供任何性能优势?

    性能方面,joinable 线程与 detached 线程之间没有区别。唯一的区别是,对于分离的线程,它的资源(例如线程堆栈和任何相关的堆内存等等——构成这些“资源”的确切内容是特定于实现的)。

    不在可连接(默认)线程上执行 pthread_join() 是否合法?

    是的,不加入线程是合法的。 pthread_join 只是一个方便的功能,除非您需要,否则绝不需要使用。但请注意,创建的线程默认是可加入线程。

    您可能想要加入的一个示例是线程执行在它们之间拆分的“一块”工作。在这种情况下,您需要在继续之前检查所有线程是否已完成。 Task farm parallelism 就是一个很好的例子。

    或者这样的线程应该总是在 pthread_exit()ing 之前使用 detach() 函数吗?

    没有必要。但您通常想在创建时决定是要 joinable 还是 detached 线程。


    请注意,虽然可以通过调用pthread_attr_setdetachstate 设置属性PTHREAD_CREATE_DETACHED 来创建可分离线程,但线程决定可以决定在任何时间点分离自身,例如与pthread_detach(pthread_self())。此外,具有另一个线程的线程 ID (pthread_t) 的线程可以与 pthread_detach(thread_id); 分离。

    【讨论】:

    • “退出主线程”和“退出整个程序/应用程序”有什么区别?
    • @YdAhhrk 从主线程调用pthread_exit 只会退出该线程,如果有其他线程在运行,该进程将继续运行。这就是我所说的“退出主线程”的意思。 OTOH,例如,从任何线程调用 exit 都会退出整个进程/应用程序。
    猜你喜欢
    • 2014-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-11
    • 1970-01-01
    • 2013-12-04
    相关资源
    最近更新 更多