Обычный шаблон для одноэлементного класса похож на
static Foo &getInst()
{
static Foo *inst = NULL;
if(inst == NULL)
inst = new Foo(...);
return *inst;
}
Однако я понимаю, что это решение не является потокобезопасным, так как 1) конструктор Foo может быть вызван более одного раза (что может или не имеет значения), и 2) inst не может быть полностью сконструирован до того, как он будет возвращен в другой поток.
Одним из решений является обертка мьютекса вокруг всего метода, но затем я плачу за накладные расходы синхронизации, после того как я действительно нуждаюсь в этом. Альтернатива - это что-то вроде
static Foo &getInst()
{
static Foo *inst = NULL;
if(inst == NULL)
{
pthread_mutex_lock(&mutex);
if(inst == NULL)
inst = new Foo(...);
pthread_mutex_unlock(&mutex);
}
return *inst;
}
Это правильный способ сделать это, или есть ли какие-то подводные камни, о которых я должен знать? Например, существуют ли какие-либо проблемы с порядком статического инициализации, которые могут возникнуть, т.е. Всегда гарантированно будет NULL при первом вызове getInst?