Pull to refresh
4
0

User

Send message

У вас тоже гонка.

Где? В статье не используется mutex вообще. Если речь про комментарий, то там так и написано, что это гонка.

Singleton* Singleton::Instance() 
{
   if(!instance) 
   {
      std::lock_guard<std::mutex> lock(mutex);
      if(!instance)
         instance = new Singleton;
   }
   return instance;
}

С точки зрения гонки этот код ничем не лучше того, что был в предыдущем комментарии.

Это синглтон.

И в статье как раз сказано, что синглтона из GoF не будет, так как ...

Плохо, но хотя бы можно свалить вину на авто-завершение слова.

Спасибо, исправил.

Поподробней можно, где там data race.

В книге "Design Patterns" приводиться следующий пример.

class Singleton {
public:
   static Singleton* Instance();
protected:
   Singleton();
private:
   static Singleton* _instance;
};
Singleton* Singleton::Instance () {
   if (_instance == 0) {
      _instance = new Singleton;
   }
   return _instance;
}

Как известно, одновременное чтение и запись одной и той же неатомарной переменной из разных потоков — data race (оно же UB). Что и происходит, если поток 1 записывает _instance (строка 3), а поток 2 читает (строка 2).

Но это еще нормально, ведь это 90-ые годы, тогда еще многопоточки в стандарте не было. Просто не нужно использовать его в многопоточной программе, ну и хотя бы добавить delete _instance.

Мне больше нравится такое написание (код ниже), которое, как ни странно, встречается нередко.

Singleton* Singleton::Instance() 
{
   if (!instance) 
   {
      std::lock_guard<std::mutex> lock(mutex);
      instance = new Singleton;
   }
   return instance;
}

Что автор хочет этим сказать? Что это можно использовать в многопоточной программе или зачем тогда lock_guard?

По факту, здесь тот же data race.

Information

Rating
Does not participate
Registered
Activity