سؤال

I have read many questions considering thread-safe double checked locking (for singletons or lazy init). In some threads, the answer is that the pattern is entirely broken, others suggest a solution.

So my question is: Is there a way to write a fully thread-safe double checked locking pattern in C++? If so, how does it look like.

We can assume C++11, if that makes things easier. As far as I know, C++11 improved the memory model which could yield the needed improvements.

I do know that it is possible in Java by making the double-check guarded variable volatile. Since C++11 borrowed large parts of the memory model from the one of Java, so I think it could be possible, but how?

هل كانت مفيدة؟

المحلول

Simply use a static local variable for lazily initialized Singletons, like so:

MySingleton* GetInstance() {
  static MySingleton instance;
  return &instance; 
}

The (C++11) standard already guarantees that static variables are initialized in a threadsafe manner and it seems likely that the implementation of this at least as robust and performant as anything you'd write yourself.

The threadsafety of the initialization can be found in §6.7.4 of the (C++11) standard:

If control enters the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for completion of the initialization.

نصائح أخرى

Since you wanted to see a valid DCLP C++11 implementation, here is one.

The behavior is fully thread-safe and identical to GetInstance() in Grizzly's answer.

std::mutex mtx;
std::atomic<MySingleton *> instance_p{nullptr};

MySingleton* GetInstance()
{
    auto *p = instance_p.load(std::memory_order_acquire);

    if (!p)
    {
        std::lock_guard<std::mutex> lck{mtx};

        p = instance_p.load(std::memory_order_relaxed);
        if (!p)
        {
            p = new MySingleton;
            instance_p.store(p, std::memory_order_release);
        }
    }

    return p;
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top