Item38 Be aware of varying thread handle destructor behavior

原创 2017年04月29日 23:45:19

   在Item37中解释过一个状态为joinablestd::thread对象其底层对应一个系统线程。std::future对象和std::thread比较类似,一个future对象也对应着一个系统线程。尽管如此这两者在析构的时候其行为也是不一样的。在Item37中已经提到过一个joinable状态的std::thread对象在析构的时候会导致程序terminate,这是因为无论是调用join还是detach都是一个糟糕的行为,这个在Item37中已经进行了解释。而本文所说的std::future对象,它的析构有的时候类似于隐式调用join,有的时候则是类似于隐式调用detach,甚至两者都不是,但是std::future不会导致程序terminate

   既然谈到了std::future,那就来进一步看一下std::future到底是什么东西,这个对象对于在异步编程中有很大的作用,可以异步获取线程的执行结果,相当于是一个channel,用来链接调用者和被调用者,被调用者通常会异步的将结果写入到这个channel中(通常是std::promise),调用者通过std::future对象来获取写入的结果,整个过程如下图:

这里写图片描述

   看到上面这个图,你或许会奇怪,这个结果是保存在哪呢?首先肯定是不能放在std::promise对象的,因为结果可能是在调用future对象获取时早已保存起来了,那么被调用者运行结束会将std::promise析构,如果结果保存在这个对象中那就会导致结果丢失了。那么能否放在std::future对象里面呢? 同样也不行,因为std::future可以用来创建std::shared_future,那么就需要将结果保存在每一个future对象中,会导致这个结果被多次拷贝和复制,或许可以使用引用计数的方式来记录当前有多少个future对象关联到这个结果中,这也不失为一种方法。但是无论是何种方式,都会造成一定的开销,算不上是一个不错的方式。因此C++11将结果保存在一个特殊的位置,这个位置被称为共享状态。可以简单的使用下面这张图来表示它们之间的关系:

这里写图片描述

​这个共享状态很重要,因为std::future对象的析构行为和这个状态息息相关,这也是本文要讨论的主题。

  1. 通过std::async发起的non-deferred策略的task,其返回的std::future,并且是最后一个引用共享状态的,其析构会一直阻塞,直到这个task运行结束,相当于隐式的做了join
  2. 其他形式的std::future对象的析构就是简单的析构,对于异步运行的task来说,这类似于隐式调用detach,对于deferred策略运行的task来说,相当于这个task将不会运行。

   让我们把std::future析构会隐式进行join这个行为进一步细化一下,只要满足下列三个条件的情况,std::future的析构才会是隐式的做join。

  1. 这个std::future是通过std::async创建的,并且引用了一个共享状态
  2. std::async运行任务的时候指定的运行策略是std::launch::async
  3. 这个future对象是最后一个引用共享状态的对象

​   std::future的这种特殊的析构行为让我们的程序行为变得不可预测,特别是我们没有办法知道哪个 future会隐式的join,哪些又是detach,从std::future对象本身来看是无法看出来的。尽管如此,但是我们知道,凡是从std::async创建的std::future都有可能是隐式的join,而其他方式创建的std::future对象则不是,比如通过std::packaged_task创建的std::future,其析构就不会隐式的进行join

版权声明:本文为博主原创文章,未经博主允许不得转载。 举报

相关文章推荐

【计算机视觉文章阅读之一】Perspective-aware Manipulation of Portrait Photos_siggraph2016

Perspective-aware Manipulation of Portrait Photos 对人脸进行多视角转化处理这篇文章是siggraph2016上的一股清流,siggraph上的文章一般...

Self-aware value network in the context of i4.0 工业4.0背景下,具有感知能力的价值网络

In 2009 when I was discussing with people on a BBS about manufacturing information systems, I made a...

我是如何成为一名python大咖的?

人生苦短,都说必须python,那么我分享下我是如何从小白成为Python资深开发者的吧。2014年我大学刚毕业..

论文:The Role of Emotions in Context-aware Recommendation总结

上下文推荐系统尝试利用不同的上下文去适应用户偏好,而且这被证明在很多不同的领域上都能提高推荐的精确性。情绪是最流行的上下文变量,而很少研究人研究情绪是怎样作用在推荐上的——特别是情绪变量的用法除了单单...

Effective Objective-C 2.0: Item 38: Create typedefs for Common Block Types

Item 38: Create typedefs for Common Block Types Blocks have an inherent type; that is, they can be ...
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)