Proper implementation in C ++ thread-safe singleton pattern

Why is not thread safe DCLP

DCLP (Double Checked Locking Pattern), i.e., the subject bis lock mode:

class Foo {
public:
    static Foo* getInstance() noexcept {
        if (nullptr == s_pInstance) {
            std::lock_guard<std::mutex> lock(s_mutex);
            if (nullptr == s_pInstance) {
                s_pInstance = new Foo();
            }
        }

        return s_pInstance;
    }

private:
    static Foo* volatile s_pInstance;
    static std::mutex s_mutex;
};

In C ++, volatile keyword only guarantee the visibility of the data, does not guarantee data consistency. When it is determined outside of the s_pInstancenon-empty, due to possible rearrangement instruction, then the object may not really good configuration, such that the program can not be executed in accordance with a predetermined behavior.

The new standard better solutions

In C ++, initialize static local variable takes place in the first execution of the program variable declaration:

static Foo* getInstance() {
    static Foo s_instance;
    return &s_instance;
}

In C ++, 98, did not consider thread safety problem simply with a semantic condition is determined to achieve this:

static bool s_initialized = false;
static char s_buf[sizeof(Foo)];

static Foo* instance()
{
    if (!s_initialized) {
        s_initialized = true;
        new (s_buf) Foo();
    }

    return (reinterpret_cast<Foo*>(s_buf));
}

C ++ 11 defines thread-safe behavior, as is the content of section 6.7 of the draft standard:

such a variable is initialized the first time control passes through its declaration; such a variable is considered initialized upon the completion of its initialization. If the initialization exits by throwing an exception, the initialization is not complete, so it will be tried again the next time control enters the declaration. If control enters the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for completion of the initialization. If control re-enters the declaration recursively while the variable is being initialized, the behavior is undefined.

  • If an exception is thrown initialization will remain uninitialized state
  • If you are initialized, other initialization statement running thread is blocked
  • If the thread is initializing the recursive call initialization statement undefined behavior

Guess you like

Origin www.cnblogs.com/HachikoT/p/12142869.html