使用 std::async 时死锁,将来作为成员
Deadlock when using std::async with future as member
我将我们的应用程序从Objective-C和Cocoa转移到C++。 在Objective-C中,我经常使用Grand Central Dispatch和非常方便的dispatch_async功能。
当移动到 C++11 时,我发现 std::async 是最接近的等价物。 我正在使用它的斯科特迈耶斯变体,以确保它真的是异步调用的:
template<typename F, typename... Ts>
inline auto NLA_async(F&& f, Ts&&... params)
{
return std::async(std::launch::async,
std::forward<F>(f),
std::forward<Ts>(params)...);
}
我了解到,如果未分配返回的未来,该函数实际上不会异步调用,因为未来 d'tor 将等待异步块完成。
void foo()
{
NLA_async([]{ // run long task async });
// future returned from NLA_async not captured
// -> std::future d'tor waits for block to be finished
}
所以我想我只是将 future 分配给一个类成员,以便它至少在大多数情况下异步调度(不理想,但我认为这是一个快速而肮脏的解决方法(。到目前为止,这运作良好。
但是,我遇到了我还不明白的僵局。 看起来该块可能同时执行两次,这在我的情况下会导致死锁。
你可以在这里看看:
http://coliru.stacked-crooked.com/a/dc4fcbaff370f1b9
谁能解释为什么同时执行两次?
编辑: 在我的特殊情况下,问题是在异步块结束时,代码锁定互斥锁,执行一些工作,然后解锁互斥锁。在这一点上,我们陷入了僵局。看起来正在运行的异步块在完成之前被删除,因为互斥锁保持锁定状态,尽管它不应该(没有 return 语句或任何可以解释为什么它不会解锁互斥锁的东西(。
两个线程异步运行的问题可能与以下事实有关:创建未来并将其分配给成员变量不会一步到位。
首先,创建它并启动线程。然后,在等待第一个线程完成时将其分配给成员变量。
感谢无用指出这一点!
相关文章:
- 将成员变量添加到共享库中的类中,不会破坏二进制兼容性吗
- 对RValue对象调用的LValue ref限定成员函数
- 为什么使用 "this" 指针调用派生成员函数?
- 具有奇怪重复模板模式的派生类中的成员变量已损坏
- 助记符和指向成员语法的指针
- 用于访问容器<T>数据成员的正确 API
- 内置函数可查看CPP中的成员变量
- 是否可以初始化不可复制类型的成员变量(或基类)
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 找不到成员对象:没有名为get_event()的成员,也处理多态性和向量
- 嵌套在类中时无法设置成员数据
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 将函数类成员映射到类本身内部
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 将Ref对象作为类成员
- 将包含C样式数组的对象初始化为成员变量(C++)
- 静态数据成员的问题-修复链接错误会导致编译器错误
- 将公共但非静态的成员函数与ALGLIB集成
- 多成员Constexpr结构初始化
- 使用 std::async 时死锁,将来作为成员