我正在学习C++中的多线程。我正在遵循一个教程,该教程给出了此示例,用于解释使用移动语义从一个线程"移动"到另一个线程的方法:
std::thread thread_1( func_1 );
std::thread thread_2 = std::move( thread_1 );
thread_1 = std::thread(func_2);
std::thread thread_3 = std::move(thread_2);
thread_1 = std::move(thread_3);
thread_1 = std::move(thread_3);
的最后一行被指出不是正确的方法,因为(据我所知):
"thread_1"和"thread_3"都是现有的线程,它们拥有一些函数(thread_1拥有func_2,thread_3拥有func_1),你应该用.detach()或.join()来管理它们的生命周期;
这是教程中给出的解释,但这对我来说没有 100% 的意义。请帮助我更好地理解为什么该行代码不是在线程之间转移所有权的正确方法的解释。谢谢!
我相信关键是你不能将正在运行的线程移动到已经在运行的线程对象上。如果这样做,程序将通过调用std::trerminate
结束。
请参阅此处的参考资料。
您只能将正在运行的线程移动到默认构造的线程对象(没有函数)或以前已从中移动或已连接/分离(将其留空)的线程对象上。
实际上,作业的右侧(thread_3
)是无关紧要的。不得分配给可联接的std::thread
对象(是操作系统线程的句柄),否则将调用std::terminate
:
http://en.cppreference.com/w/cpp/thread/thread/operator%3D
您的问题并没有显示出对std::thread
变量、std::thread
值和线程之间区别的太多了解。 这是三件不同的事情。 您的三个初始化和赋值语句将std::thread
值从一个变量移动到另一个变量。
当你移动一个std::thread
值时,你实际上是在调用一个函数:这是一个函数调用:
thread_1 = std::move(thread_3);
它调用std::thread
一个名为
std::thread::operator= (std::thread&& other)
而且,它做了三件事。 它必须首先销毁(即有效地调用)thread_1
的值,然后将thread_3
值的内脏复制到thread_1
中,最后它必须有效地"清零"thread_3
变量。
这在第一步中失败 - 破坏旧的thread_1
值 - 因为线程已经在运行。
线程不是变量,也不是变量的值。线程是操作系统内核中的一个对象,thread_1
变量的值只是操作系统对象的句柄。
std::thread
类强制实施的规则之一是,除非以前调用过detach()
方法,否则它不允许销毁正在运行的线程的句柄。detach()
方法只是设置一个标志,表示"相信我,我知道我在做什么,我不再需要句柄,因为我不需要再次对正在运行的线程施加控制。