【发布时间】:2014-10-21 00:22:48
【问题描述】:
请有人解释一下为什么这个程序中的两个线程(使用 Visual Studio 2012/2013 附带的编译器编译时)在两个 std::call_once 调用都被执行之前都被阻塞了?另一个 Visual Studio 错误(假设使用 GCC 编译时它的行为符合预期)?有人可以想出一个解决方法吗?想象一下我为缩小问题范围所经历的所有痛苦,请宽容。
#include <chrono>
#include <iostream>
#include <mutex>
#include <thread>
namespace
{
std::once_flag did_nothing;
void do_nothing()
{ }
void sleep_shorter_and_do_nothing_once()
{
std::this_thread::sleep_for(std::chrono::seconds(3));
std::cout << "1\n";
std::call_once(did_nothing, do_nothing);
std::cout << "2\n";
}
std::once_flag sleeped_longer;
void sleep_longer()
{
std::this_thread::sleep_for(std::chrono::seconds(10));
}
void sleep_longer_once()
{
std::cout << "3\n";
std::call_once(sleeped_longer, sleep_longer);
std::cout << "4\n";
}
}
int main()
{
std::thread t1(sleep_shorter_and_do_nothing_once);
std::thread t2(sleep_longer_once);
t1.join();
t2.join();
return 0;
}
详细地说,它在使用 GCC 编译时的行为与预期一样:
- 打印“3”,
- 等待 3 秒,
- 打印“1”,
- 立即打印“2”,
- 再等 6-7 秒,
- 并打印“4”。
使用 Visual Studio 2012/2013 附带的编译器进行编译时,其行为如下:
- 打印“3”,
- 等待 3 秒,
- 打印“1”,
- 再等 6-7 秒,
- 然后才立即打印“2”和“4”。
显然,这是一种不当行为。还是不行?
更新:我无法将此作为 Visual Studio 错误提交,因为我的工作帐户由于某种原因“无权为此连接提交反馈”,无论这意味着什么。我收到了 Microsoft STL 维护人员的回复,说他希望在未来的某个时间调查这个问题。
【问题讨论】: