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();
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();
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;
_sync_check = reinterpret_cast<int*>(1);
}
return *instance;
}
};
, , , , , , . , bool?:
class singleton {
private:
singleton();
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 , ( , ), , ( ).
, ? ?