繁体   English   中英

使用std :: async并以future作为成员时出现死锁

[英]Deadlock when using std::async with future as member

我将我们的应用程序从Objective-C和Cocoa转移到了C ++。 在Objective-C中,我经常使用Grand Central Dispatch和非常方便的dispatch_async函数。

转到C ++ 11时,我发现std :: async是最接近的等效项。 我正在使用它的Scott Meyers变体,以确保它确实被异步调用:

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)...);
}

我了解到,如果未分配返回的future,则该函数实际上不会被异步调用,因为future 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语句或任何可以解释为什么不解锁互斥锁的东西)。

两个线程异步运行的问题可能与以下事实有关:创建未来并将其分配给成员变量不会一步就发生。

首先,创建它并启动线程。 然后,在等待第一个线程完成时将其分配给成员变量。

感谢Useless指出这一点!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM