【发布时间】:2012-09-22 18:32:30
【问题描述】:
(假设 VC++ 2010:(1)可以使用 /volatile:ms,(2)还没有 std::atomic,(3)没有线程安全的静态变量初始化,(4)没有 std::call_once)
如果我有一个普通的 C 指针,我可以实现以下双重检查锁定模式以避免每次锁定的成本:
static volatile void * ptr = nullptr;
//...
if ( ptr == nullptr)
{
// Acquire Lock
if (ptr == nullptr)
{
// some code
// ptr = ...; // init ptr
}
// Release Lock
}
// ....
从 VC++ 2005 开始,volatile 确保上面的代码是正确的。假设我可以接受代码不可移植。
现在假设我需要用 std::shared_ptr 或 boost::shared_ptr 替换普通指针,我将如何做同样的事情?如何使 shared_ptr 不稳定?我需要另一个 volatile 标志吗?
【问题讨论】:
-
不,它没有。双重检查锁定是错误的。
-
是什么让您相信
volatile使该代码正确? -
如果您将
static volatile void *ptr = nullptr;更改为std::atomic<void*> ptr = nullptr;,则双重检查锁定将起作用。这假设 C++11。 -
@Daniel :
volatile保证了 VC++ 2005+ 中的内存屏障。因此“自 VC++ 2005 起,volatile 确保上述代码正确。”;-] -
是的,我确实假设 /volatile:ms 使用 VC++。 (因此,代码在标准 C++ 中是不可移植的,甚至是不正确的)。抱歉没有说清楚。我的问题应该是如何对 VS2010 中的 std::shared_ptr 或 boost::shared_ptr 做同样的事情(其中 std::atomic 尚不可用。)
标签: c++ c++11 locking shared-ptr lazy-initialization