C++ 为什么不是';boost::shared\u ptr volatile中的引用计数器是否为?

C++ 为什么不是';boost::shared\u ptr volatile中的引用计数器是否为?,c++,multithreading,boost,shared-ptr,C++,Multithreading,Boost,Shared Ptr,在boost::shared_ptr析构函数中,执行以下操作: if(--*pn == 0) { boost::checked_delete(px); delete pn; } 其中,pn是指向引用计数器的指针,其类型定义为 shared_ptr::count_type -> detail::atomic_count -> long 考虑到上面的共享解构器中的线程使用和非原子的0-check-and-deletion,我本来希望long是volatile long

boost::shared_ptr
析构函数中,执行以下操作:

if(--*pn == 0)
{
    boost::checked_delete(px);
    delete pn;
}
其中,
pn
是指向引用计数器的指针,其类型定义为

shared_ptr::count_type -> detail::atomic_count -> long
考虑到上面的
共享解构器中的线程使用和非原子的0-check-and-deletion,我本来希望
long
volatile long
。为什么它不易挥发

编辑:


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

volatile
实际上与线程无关。请参阅。

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

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

我相信
shared\u ptr
在可能的情况下使用原子操作,这隐含地提供了一个内存屏障。否则它会退回到互斥锁,互斥锁还提供了一个内存屏障

有关更多详细信息,请参阅或

编辑

在一般情况下,
count\u类型
不是
long
。它可以转换为
long
。如果查看
atomic_count.hpp
,只有在没有线程可用的情况下才应用typedef to long(当然,在这种情况下,不需要同步)。否则,它将使用
boost/smart\u ptr/detail/atomic\u count\u pthreads.hpp
boost/smart\u ptr/detail/atomic\u count\u win32.hpp
中定义的实现或列出的其他文件之一。这些都是同步的包装类,确保所有操作都以原子方式完成。

您误读了代码<如果代码未使用多线程,则代码>原子计数
仅定义为长:

#ifndef BOOST_HAS_THREADS

namespace boost
{

namespace detail
{

typedef long atomic_count;

}

}

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

#endif

“我相信shared_ptr在可能的情况下使用原子操作”-在我引用的析构函数示例中没有,这就是我现在的问题所在…好吧,使变量
易失性
不会改变任何东西。你说得对,递减并比较长与零看起来确实很危险,但这取决于指针类的其他成员在做什么。@jalf:好吧,那就是你失去了我。;-)现在,在我的示例中,两个线程进入共享的ptr dtor,“指针类的其余部分”不做任何其他事情。@Johann:但是,即使它是一个bug,
volatile
如何修复它?@jalf:好的,对不起,我不够明确-我同意(在阅读了你的链接后)volatile已经失效。但鉴于这一事实,我无法在dtor示例中证明“这取决于指针类的其余部分在做什么”。注意-我不是说你错了,我只是想理解。如果在不同的线程上执行,你会说析构函数中对计数器的上述处理没有问题吗?顺便说一句,你在哪里找到这段代码的?谢谢!编辑问题以澄清问题。(已接受日本航空公司的答复)