【问题标题】:Do you need to join a cancelled thread? (pthreads)您需要加入已取消的线程吗? (线程)
【发布时间】:2012-01-23 16:53:42
【问题描述】:

当您使用 PThreads 进行取消时,我对清理顺序有点困惑。通常,如果您的线程被分离,它会在终止时自动清理。如果没有分离,则需要加入它来回收系统资源。

我正在阅读的教科书陈述了以下内容,奇怪的是,关于取消,加入是可选的:

"如果您需要知道线程实际终止的时间,您必须 取消后调用 pthread_join 加入它。”

那么,我是否需要加入已取消的线程以释放其资源 - 如果不需要,那为什么?

【问题讨论】:

    标签: c++ multithreading pthreads


    【解决方案1】:

    TLPI 是这样说的:

    收到取消请求后,线程的可取消性为 enabled 和 deferred 在下一次达到取消时终止 观点。如果线程没有分离,那么线程中的某个其他线程 进程必须加入它,以便防止它成为 僵尸线程

    此外,由于取消线程通常不会立即完成(阅读有关“取消点”的更多信息)而不加入您无法确定线程实际上已被取消。

    【讨论】:

    • 如果在取消之前设置为分离模式,会不会变成僵尸线程?还是我应该提出一个新问题:p
    • @w00te 这取决于你。但是引用确实说“如果线程没有分离”。如果您分离一个线程,则无需(也没有办法)加入它。一旦你分离了一个线程,就没有办法让它再次可连接。
    • Posix 标准没有提到僵尸线程,但是如果我理解正确的话,一个被分离的线程永远不会变成僵尸线程。 (从逻辑上讲,分离一个线程与告诉系统在它完成后立即为您执行连接具有相同的效果。)
    【解决方案2】:

    来自man pthread_join

    在取消的线程终止后,与该线程的连接使用 pthread_join(3) 获得 PTHREAD_CANCELED 作为线程的退出状态。 (加入线程是知道取消的唯一方法 完成。)

    似乎加入对于执行来说不是必需的,如果你想知道你做了什么实际上是成功的。

    【讨论】:

      【解决方案3】:

      来自pthread_cancel()Doccumentation

      在取消的线程终止后,使用 pthread_join(3) 与该线程的连接将获得 PTHREAD_CANCELED 作为线程的退出状态。 (加入线程是知道取消已完成的唯一方法。)

      【讨论】:

      • 我明白,但我的问题是 - 如果我不关心取消确认,我是否还需要调用 pthread_join,或者这是资源已经存在的某种特殊情况被释放并且它是可选的(这就是我提到的报价中的意思)?
      • @w00te:我认为在这种情况下没有必要。
      • @Als 是的。您将取消与分离混淆了。你不必加入一个分离的线程——事实上,这样做是错误的。但是,除非线程已被分离,否则您必须执行连接或分离它。
      • @JamesKanze:总结一下:取消线程不会从操作系统维护的表中删除条目,它只会杀死线程但只有joindetach 可以删除条目,否则它仍然像僵尸一样挂在系统中。
      • @Als 取消线程甚至不会杀死线程;它的作用取决于目标线程,可以忽略或显式处理 (pthread_testcancel)。它对线程的可连接性没有任何影响:只有detach 可以改变这一点。并且“最终应该为每个创建的线程调用 pthread_join() 或 pthread_detach() 函数,以便可以回收与线程关联的存储。” (引用自 Posix 标准)
      【解决方案4】:

      使用 pthread 的线程可以有以下取消状态:

      PTHREAD_CANCEL_ENABLE PTHREAD_CANCEL_DISABLE

      如果您尝试取消线程,您不会 100% 知道线程是否真的会被取消。如果线程真的被取消,使用连接会向您传递信息。还需要考虑取消类型以及用于设置取消类型和状态的相应 pthread 函数:

      int pthread_setcancelstate (int state, int *oldstate); int pthread_setcanceltype (int type, int *oldtype);

      这是从http://www.ijon.de/comp/tutorials/threads/cancel.html借来的示例代码

      编辑:要么我太愚蠢而无法发布几行代码,要么格式化程序今天真的让我很紧张。请在上面的链接中查找代码。

      【讨论】:

        【解决方案5】:

        如果线程中出现问题或者它以某种方式停止,它将始终由操作系统进行整理。所以一切都很好,很安全。

        如果你必须确定它实际上已经停止执行,你只需要加入线程,比如合并两个并行任务。 (例如,如果您有多个线程在拆分结构的各个部分上工作,则需要将它们全部连接起来,例如等到它们全部完成后,当您想再次组合该结构时)

        【讨论】:

        • 这是错误的。除非线程已被分离,否则系统必须保留它直到它被加入,以便加入工作。这需要资源,这意味着如果您系统地执行此操作,您最终会耗尽资源。
        猜你喜欢
        • 1970-01-01
        • 2021-11-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-10-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多