我正在学习C ++中的互斥体,并且遇到以下代码的问题(摘自N. Josuttis的“C ++标准库”)。
我不明白为什么它阻止/抛出除非我在主线程中添加 this_thread::sleep_for
(然后它不会阻塞并执行所有三个调用)。
编译器是从命令行使用的cl.exe。
#include <future>
#include <mutex>
#include <iostream>
#include <string>
#include <thread>
#include <chrono>
std::mutex printMutex;
void print(const std::string& s)
{
std::lock_guard<std::mutex> lg(printMutex);
for (char c : s)
{
std::cout.put(c);
}
std::cout << std::endl;
}
int main()
{
auto f1 = std::async(std::launch::async, print, "Hello from thread 1");
auto f2 = std::async(std::launch::async, print, "Hello from thread 2");
// std::this_thread::sleep_for(std::chrono::seconds(1));
print(std::string("Hello from main"));
}
答案 0 :(得分:11)
我认为您所看到的是async
的MSVC实施(与future
结合)的一致性问题。我相信它是not conformant。我可以用VS2013重现它,但无法用gcc重现这个问题。
崩溃是因为主线程在其他两个线程完成之前退出(并开始清理)。
因此,两个期货的简单延迟(sleep_for
)或.get()
或.wait()
应该为您解决。因此修改后的main
可能看起来像;
int main()
{
auto f1 = std::async(std::launch::async, print, "Hello from thread 1");
auto f2 = std::async(std::launch::async, print, "Hello from thread 2");
print(std::string("Hello from main"));
f1.get();
f2.get();
}
支持明确等待或克服定时“睡眠”。
有关一致性的说明
来自Herb Sutter的提案更改了从future
返回的async
的共享状态的等待或阻止。这可能是MSVC行为的原因,可以看作已实施该提案。我不确定该提案的最终结果是什么,或者它与C ++ 14的集成(或其中的一部分)。至少w.r.t.阻止从future
返回的async
,看起来MSVC行为没有进入规范。
值得注意的是,§30.6.8/ 5中的措辞有所改变;
来自C ++ 11
对共享创建的共享状态的异步返回对象的等待函数的调用 通过此
一样async
调用将阻塞,直到关联的线程完成,就像加入
To C ++ 14
对共享创建的共享状态的异步返回对象的等待函数的调用 通过此
async
调用将阻塞,直到关联的线程完成,就好像已加入,或其他时间 退出
我不确定如何指定“超时”,我认为它是实现定义的。
答案 1 :(得分:1)
std::async
会返回future。如果get
或wait
未被调用,则会destructor阻止:
如果满足以下所有条件,它可能会阻塞:共享状态是通过调用std :: async创建的,共享状态尚未就绪,这是对共享状态的最后一次引用。
有关该主题的详细处理,请参阅std::futures from std::async aren't special!。
答案 2 :(得分:1)
在main
:
f1.wait();
f2.wait();
这将确保线程在main
存在之前完成。