并发std::call_once调用
Concurrent std::call_once calls
请有人解释一下,为什么在执行两个std::call_once
调用之前,此程序中的两个线程(使用Visual Studio 2012/2013附带的编译器编译时)都会被阻止?另一个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 << "1n";
std::call_once(did_nothing, do_nothing);
std::cout << "2n";
}
std::once_flag sleeped_longer;
void sleep_longer()
{
std::this_thread::sleep_for(std::chrono::seconds(10));
}
void sleep_longer_once()
{
std::cout << "3n";
std::call_once(sleeped_longer, sleep_longer);
std::cout << "4n";
}
}
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"answers"4"
很明显,这是一种不当行为。或者不是吗?
更新:我不能将其作为Visual Studio错误提交,因为我的工作帐户由于某种原因"无权提交此连接的反馈",不管这意味着什么。我收到了微软STL维护人员的回复,他希望在未来的某个时候调查这个问题。
我收到了微软STL维护人员的回复,称该错误已在Visual Studio 2015中修复。
它更喜欢行为不端
"对once_flag对象上的call_once的有效调用的完成与对同一once_flag对象上的所有后续调用同步。"(N3242,30.4.4.2类-3)。
相关文章:
- 什么时候调用组成单元对象的析构函数
- 对RValue对象调用的LValue ref限定成员函数
- 为什么使用 "this" 指针调用派生成员函数?
- 函数调用中参数的顺序重要吗
- OpenGL - 在抛出"__gnu_cxx::recursive_init_error"实例后终止调用?
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 在c++类上调用void函数
- 为什么 std::unique 不调用 std::sort?
- 调用专用模板时出错"no matching function for call to [...]"
- 选择要调用的构造函数
- C++为什么尽管我调用了void函数,它却不起作用
- 构造函数正在调用一个使用当前类类型的函数
- 变量没有改变?通过向量的函数调用
- 没有为自己的结构调用列表推回方法
- 调用'begin(int [n])'没有匹配函数
- 什么时候调用析构函数
- 如何用参数值调用函数(仅在运行时已知)
- std::cout.imbue()多重调用
- 函数何时会在c++中包含stack_Unwind_Resume调用