6

boost::shared_ptr析构函数中,这是完成的:

if(--*pn == 0)
{
    boost::checked_delete(px);
    delete pn;
}

wherepn是指向引用计数器的指针,其类型定义为

shared_ptr::count_type -> detail::atomic_count -> long

考虑到线程使用和上面析构函数中的非原子 0-check-and-deletion,我本来希望是long。为什么不挥发?volatile longshared_ptr

编辑:

事实证明,我查看了未指定多线程使用时使用的标头(atomic_count.hpp)。在 atomic_count_win32.hpp 中,为多线程使用正确实现了减量。

4

3 回答 3

16

因为volatile对于多线程来说不是必需的,并且没有任何好处,但可能会破坏许多优化。

为了确保对变量的安全多线程访问,我们需要的原语是内存屏障,它提供了volatile和其他一些保证(它可以防止内存访问跨屏障重新排序,而 volatile 不会这样做)

我相信shared_ptr尽可能使用原子操作,这隐含地提供了内存屏障。否则它会退回到互斥体,它也提供了内存屏障。

请参阅为什么 volatile 在多线程 C 或 C++ 编程中不被认为有用?http://software.intel.com/en-us/blogs/2007/11/30/volatile-almost-useless-for-multi-threaded-programming/了解更多详情

在一般情况下,编辑不是
count_type。它可以转换为. 如果您查看,则只有在没有线程可用的情况下才应用 typedef 到 long (当然,在这种情况下,不需要同步)。否则,它使用在或列出的其他文件之一中定义的实现。这些是同步的包装类,可确保所有操作都以原子方式完成。longlongatomic_count.hppboost/smart_ptr/detail/atomic_count_pthreads.hppboost/smart_ptr/detail/atomic_count_win32.hpp

于 2010-03-26T11:05:49.397 回答
8

volatile几乎与线程无关。见这里

于 2010-03-26T11:04:10.427 回答
2

你误读了代码。atomic_count如果代码不使用多线程,则简单地定义为 long:

#ifndef BOOST_HAS_THREADS

namespace boost
{

namespace detail
{

typedef long atomic_count;

}

}

#elif //... include various platform-specific headers that define atomic_count class

#endif
于 2010-03-26T11:51:15.053 回答