Проблема в том, что поток может быть прерван после проверки, равен ли m_mutex 0, но не раньше, чем он создаст мьютекс, позволяя другому потоку проходить через тот же код.
Не назначайте m_mutex сразу. Создайте новый мьютекс, а затем выполните обмен атомарными сравнениями.
Вы не упоминаете свою целевую платформу, но в Windows:
MyClass::GetResource()
{
if (m_mutex == 0)
{
// make a new mutex object
MyMutex* mutex = new MyMutex();
// Only set if mutex is still NULL.
if (InterlockedCompareExchangePointer(&m_mutex, mutex, 0) != 0)
{
// someone else beat us to it.
delete mutex;
}
}
m_mutex->Lock();
В противном случае замените любой функцией сравнения / обмена, которую обеспечивает ваша платформа.
Другим вариантом является использование поддержки однократной инициализации , которая доступна в Windows Vista и более поздних версиях, или просто предварительное создание мьютекса, если вы можете.