【发布时间】:2022-10-23 21:14:56
【问题描述】:
在下面的程序中,一个线程(main)正在执行thread::join,另一个线程(x)调用thread::detach:
#include <thread>
#include <iostream>
int main(void) {
auto t = std::thread([] {
std::this_thread::sleep_for( std::chrono::milliseconds(1000) );
} );
auto x = std::thread([&t] {
std::this_thread::sleep_for( std::chrono::milliseconds(500) );
if ( t.joinable() )
{
std::cout << "detaching t..." << std::endl;
t.detach();
}
} );
std::cout << "joining t..." << std::endl;
t.join();
x.join();
std::cout << "Ok" << std::endl;
return 0;
}
它在 GCC 的 libstdc++ 和 Clang 的 libc++ 打印中工作正常
joining t...
detaching t...
Ok
但在 Visual Studio 中,程序在打印 Ok 之前以非零退出代码终止。在线演示:https://gcc.godbolt.org/z/v1nEfaP7a
它是 Visual Studio 中的错误还是程序包含一些未定义的行为?
【问题讨论】:
-
std::thread对象本身不是线程安全的。从两个线程对它调用join和joinable同时通过数据竞争表现出未定义的行为。 -
这与例如有什么不同?一个线程推送到一个向量和另一个弹出?
-
当另一个线程调用
detach函数时,一个线程耐心地等待thread通告它所代表的线程已经完成,因此thread不再代表一个线程。你可以很容易地得到另一个明显的结果,线程在连接之前就被分离了。或者你可以让线程被分离尽管它正在加入。这三种情况都令人不快。不要这样做。
标签: c++ multithreading language-lawyer