我刚刚开始阅读C ++ Concurrency In Action 2012.在第2章中,它显示了一个被调用和连接的线程。连接不是创建线程的原子操作。我的意思是线程以std:thread t(...)
开头,在后续行中执行join
。我的假设是,当创建一个线程时,它可以随时开始执行,包括立即执行。如果它立即开始执行并在创建程序开始执行之前终止,那么join
将失败。
如果使用t.joinable()
,则会出现同样的问题。
如果我的猜测是正确的,则无法保证join
能够成功且joinable()
谓词无效。我错过了什么?
答案 0 :(得分:1)
thread
对象可能表示执行的线程,但这并不意味着实际的执行线程正在运行(即使它在某个时间点)。
换句话说,当你构造一个thread
对象(代表一个实际的执行线程,即你使用非默认构造函数)并且它的相关执行线程结束时,这个事件不更改thread
对象的状态。它仍然是joinable()
。
更确切地说,根据[thread.thread.class],非默认构造函数的后置条件是get_id() != id()
(即对象表示实际的执行线程)。更改该条件的唯一方法是join()
或detach()
(或移动它) - 执行线程已完成或未完成的事实不会更改get_id()
的返回值。该标准的说明澄清了可以改变条件的唯一事件:
[注意:线程对象在默认构造之后,移动之后或成功调用分离或连接之后不表示执行的线程。 - 结束说明]
答案 1 :(得分:0)
一个连接方法实质上是说“阻塞执行,直到线程完成,此时从我的连接调用返回”。
如果线程在您调用join时已经运行并退出,它将立即返回。如果线程仍在运行,那么您的加入调用将被阻止,直到线程完成,此时它将返回。在这两种情况都不会出现故障。
以下是join函数文档的确切文本:
该函数在线程执行完成时返回。
这将使此函数返回的时刻与完成同步 线程中的所有操作:这会阻止执行 在调用函数之前调用此函数的线程 施工回报(如果还没有)。