【问题标题】:Is it acceptable and safe to pthread_join myself?自己 pthread_join 是否可以接受和安全?
【发布时间】:2013-05-09 14:56:49
【问题描述】:

我的设置有点像这样:

void* work(void*) { while (true) {/*do work*/} return 0;}

class WorkDoer
{
private:
    pthread_t id;
public:
    WorkDoer() { pthread_create(&id, NULL, work, (void*)this); }
    void Shutdown() { pthread_join(id, NULL); /*other cleanup*/ }
}

在某些情况下,Shutdown() 是从主线程调用的,而在其他一些情况下,我想从线程本身调用 shutdown(之后立即从该线程返回)。

pthread_join() 的文档说,如果调用线程与传递的线程相同,它将返回 EDEADLK

我的问题是:这样做可以吗?如果可以,是否安全? (因此忽略连接失败,因为无论如何我都会很好地结束线程?)或者,这是应该避免的事情吗?

【问题讨论】:

    标签: c++ thread-safety pthreads


    【解决方案1】:

    您当然可以从正在运行的线程本身调用pthread_join(),并且您发现调用本身会正确处理它并为您提供错误代码。但是,有几个问题:

    1. 这没有任何意义,因为加入不会加入任何东西。它只会告诉您您做错了什么。
    2. 线程本身在调用pthread_join() 时不会退出。
    3. 即使线程存在,它的状态也不会被正确清理。其他一些线程(即您的应用程序的主线程)应该调用pthread_join(),除非该线程被创建为“分离的”。

    因此,换句话说,这种方法与您的程序中的错误一样可以接受。

    作为一种解决方案,我建议重新审视设计并确保在正确的时间和正确的位置调用Shutdown()。毕竟,“shutdown”这个名字在这里没有多大意义,因为它不会关闭任何东西。它所做的只是等待线程完成并在完成后清理其状态。

    当你想结束工作线程时,要么从线程例程返回,要么调用pthread_exit()。然后确保启动线程的人通过调用 pthread_join() 来清理内容。

    如果您想强制线程停止,请考虑使用pthread_kill() 向线程发出信号,或者,实现某种消息传递,您可以使用它来“告诉”线程停止执行它正在执行的任何操作。

    【讨论】:

    • 这正是我正在寻找的解释。非常感谢!
    【解决方案2】:
       The pthread_join() function may fail if:
    
       EDEADLK
              A deadlock was detected or the value  of  thread  specifies  the
              calling thread.
    

    我会说使用风险自负。

    【讨论】:

      【解决方案3】:

      为什么不让线程调用pthread_detach(pthread_self()); 然后退出。无需再致电pthread_join() 并冒着失败的风险。

      【讨论】:

      • 这种方法经常导致“清理问题”。如果分离线程指的是一些内存,甚至是静态对象,并且主线程在分离线程结束之前结束,则会发生各种损坏(并且 coredump 并不罕见)。最好适当清理和加入。
      • @Mekk: ... 或者通过调用pthread_exit() 离开main()(从线程的角度来看,这只是另一个线程)。
      • 在这种情况下谁来为全局和静态对象执行析构函数?并且在更多的 C-ish 代码中出现 atexits?
      • @Mekk:当进程结束时,这一切都完成了。
      • 相信我:这个“进程结束”阶段比看起来要复杂得多,至少在你的应用程序有各种线程需要完成一些工作并使用一些静态或全局资源的情况下这样做。我分析了许多“结束阶段”崩溃。显式加入线程(在通知它们必须结束之后)使这更易于管理。当然:如果线程是自给自足的,则不使用共享资源,并且没有人关心它是在同行之前还是之后完成,它可以分离。
      猜你喜欢
      • 1970-01-01
      • 2014-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-15
      • 2014-01-28
      • 2014-09-17
      • 2020-01-29
      相关资源
      最近更新 更多