一个线程是否会立即启动?

4
我刚开始阅读 《C++ Concurrency In Action 2012》。在第二章中,它展示了一个线程被调用和加入(join)的情景。这里的join不是与线程创建成原子操作。我的意思是说,线程是通过 std:thread t(...) 启动的,在下一行执行了加入(join)操作。我猜测,当线程被创建时,它可以随时开始执行,包括立即开始执行。如果它在创建程序开始执行之前就立即开始执行并终止,则加入(join)操作将失败。
使用 t.joinable()也会出现同样的问题。
如果我的猜测正确,那么无法保证加入(join)操作能够成功,并且 joinable() 断言也没有帮助。我是否有什么遗漏?

1
我相信即使线程已经结束,join()也会成功。否则它就没有太大用处了。有关更多详细信息,请参见joinable - iPherian
一个线程可以在挂起状态下创建,加入,然后执行吗?还是这需要通过编程来实现? - lostbits
是的,C++ 没有挂起线程的概念,因此您需要通过编程来实现。使用 条件变量 可能会起到一定作用。 - iPherian
2个回答

1
一个thread对象可以代表一个执行线程,但这并不意味着实际的执行线程正在运行(即使在某个时间点上它是在运行的)。
换句话说,当你构造一个thread对象(它代表一个实际的执行线程,即你使用非默认构造函数),并且它关联的执行线程结束时,这个事件不会改变thread对象的状态。它仍然是可加入的(joinable())。
更准确地说,根据[thread.thread.class],非默认构造函数的后置条件是get_id() != id()(即该对象代表一个实际的执行线程)。改变这个条件的唯一方法是使用join()detach()(或移动它)--执行线程是否已经完成并不会改变get_id()的返回值。标准的这个注释澄清了可以改变条件的唯一事件:

[ 注意:线程对象在默认构造、移动或成功调用分离(detach)或加入(join)后不再表示执行线程。— 结束说明 ]


0

join 方法本质上是说:“阻塞执行,直到线程完成,然后从我的调用返回。”

如果一个线程已经运行并退出,此时您调用 join,它将立即返回。如果线程仍在运行,则调用 join 将被阻塞,直到线程完成,然后它将返回。在这两种情况下都不会发生失败。

以下是 join 函数文档的确切文本:

当线程执行完成时,该函数返回。

这会使得该函数返回的时刻与线程中所有操作完成的时刻同步:它会阻塞调用该函数的线程,直到构造函数上调用的函数返回(如果尚未返回)。

http://www.cplusplus.com/reference/thread/thread/join/


哇,书中的2.7清单有多个线程创建,然后是多个加入。这似乎是非常具有欺骗性的代码,因为最长执行的程序决定了加入行为和“下一步该做什么”。有没有办法以挂起状态启动程序,并执行其他操作以获得对已创建线程的控制?这是否是线程池可以解决的问题(我还没有涉及到它们)? - lostbits
1
@ArthurSchwarez 首先,如果这个回答解决了你的问题,你应该接受它。你看到很多代码执行一堆线程然后将它们全部加入的原因很简单。基本上是在说“让所有这些线程并行执行并运行直到它们的任务完成。等待直到我所有的线程都完成,然后继续我的程序(或退出)”。如果你想要更多的细节,你应该开始一个新的问题。我在评论中回答的空间有限。但我可以说,join 不是关于“控制”,而只是等待线程存在。 - Jeffrey Phillips Freeman
@ArthurSchwarez 还有你评论中提到的另一部分内容:https://dev59.com/-18e5IYBdhLWcg3wpLor - Jeffrey Phillips Freeman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接