What is wrong with this fix to double check for blocking?

So, I've seen a lot of articles claiming that C ++ has double-checked the lock, usually used to prevent attempts to initialize a lazily created singleton by multiple threads. A normal double checked lock code reads as follows:

class singleton {
private:
    singleton(); // private constructor so users must call instance()
    static boost::mutex _init_mutex;

public:
    static singleton & instance()
    {
        static singleton* instance;

        if(!instance)
        {
            boost::mutex::scoped_lock lock(_init_mutex);

            if(!instance)           
                instance = new singleton;
        }

        return *instance;
    }
};

The problem, apparently, is the purpose of the line - the compiler can freely select the object, and then assign it a pointer, or set the pointer to where it will be selected, and then select it. The latter case violates the idiom - one thread can allocate memory and assign a pointer, but not run a single constructor before it sleeps - then the second thread will see that the instance is not zero and will try to return it, although it has not yet been built.

I , local boolean , instance. - :

class singleton {
private:
    singleton(); // private constructor so users must call instance()
    static boost::mutex _init_mutex;
    static boost::thread_specific_ptr<int> _sync_check;

public:
    static singleton & instance()
    {
        static singleton* instance;

        if(!_sync_check.get())
        {
            boost::mutex::scoped_lock lock(_init_mutex);

            if(!instance)           
                instance = new singleton;

            // Any non-null value would work, we're really just using it as a
            // thread specific bool.
            _sync_check = reinterpret_cast<int*>(1);
        }

        return *instance;
    }
};

, , , , , , . , bool?:

class singleton {
private:
    singleton(); // private constructor so users must call instance()
    static boost::mutex _init_mutex;

public:
    static singleton & instance()
    {
        static bool sync_check = false;
        static singleton* instance;

        if(!sync_check)
        {
            boost::mutex::scoped_lock lock(_init_mutex);

            if(!instance)           
                instance = new singleton;

            sync_check = true;
        }

        return *instance;
    }
};

? sync_check , , - , , . , , . , - , , . , , , - . ++ .

, , sync_check , ( , ), , ( ).

, ? ?

+5
3

, sync_check CPU. , . , sync_check true, , . CPU , sync_check, , , . . Xbox 360 Microsoft Windows.

sync_check, , ( , 0).

+5

( .net/# ) : http://msdn.microsoft.com/en-us/magazine/cc163715.aspx

, , CPU, / ( Pentium, CPU , , ) ( - , , , - , , unshared (L1), (L2)) - , ​​ . concurrency, , .

++, .net , ( / System.Threading).

, , .net 2.0 , "" ( .net ) - ++.

, ++, volatile #.

+1

" - ."

, , ( ), , , - . .

, , , .

, , ​​, .

, , , , .

Did I miss something?

Well, I’m not sure about the reordering of operations, but in this case it will change the logic, so I did not expect this to happen, but I am not an expert in this topic.

0
source

All Articles