Проектирование поточно-безопасного копируемого класса

Простой способ сделать класс потокобезопасным - это добавить атрибут мьютекса и заблокировать мьютекс в методах доступа

class cMyClass {
  boost::mutex myMutex;
  cSomeClass A;
public:
  cSomeClass getA() {
    boost::mutex::scoped_lock lock( myMutex );
    return A;
  }
};

Проблема в том, что это делает класс не копируемым.

I может заставить все работать, сделав мьютекс статическим. Однако это означает, что каждый экземпляр класса блокируется при обращении к любому другому экземпляру, потому что все они используют один и тот же мьютекс.

Интересно, есть ли лучший способ?

Я пришел к выводу, что нет лучшего путь. Сделать класс потокобезопасным с помощью атрибута private static mutex «лучше всего»: это просто, это работает и скрывает неудобные детали.

class cMyClass {
  static boost::mutex myMutex;
  cSomeClass A;
public:
  cSomeClass getA() {
    boost::mutex::scoped_lock lock( myMutex );
    return A;
  }
};

Недостатком является то, что все экземпляры класса совместно используют один и тот же мьютекс и, таким образом, излишне блокируют друг друга. Это нельзя исправить, сделав атрибут мьютекса нестатическим (таким образом, предоставив каждому экземпляру свой собственный мьютекс), потому что сложности копирования и присвоения кошмарны, если все сделано правильно.

Отдельные мьютексы, если требуется, должны управляться внешний некопируемый синглтон со ссылками на каждый экземпляр при создании.


Спасибо за все ответы.

Несколько человек упомянули о написании моего собственного конструктора копирования и оператора присваивания. Я пробовал это. Проблема в том, что у моего реального класса много атрибутов, которые всегда меняются в процессе разработки. Поддержание конструктора копирования и оператора assignmet утомительно и чревато ошибками, из-за чего ошибки трудно найти. Разрешение компилятору генерировать их для сложного класса - это огромная экономия времени и устранение ошибок.


Во многих ответах говорится о том, как сделать конструктор копирования и оператор присваивания потокобезопасным. Это требование добавляет ко всему этому еще больше сложности! К счастью для меня, мне это не нужно, так как все копирование выполняется во время установки в одном потоке.


Теперь я думаю, что лучшим подходом было бы создание крошечного класса, который будет содержать только мьютекс и критические атрибуты. . Затем я могу написать конструктор уменьшенной копии и оператор присваивания для критического класса и оставить компилятору следить за всеми другими атрибутами в основном классе.


Теперь я думаю, что лучшим подходом было бы создание крошечного класса, который бы содержал только мьютекс и критические атрибуты. Затем я могу написать конструктор небольшой копии и оператор присваивания для критического класса и оставить компилятору следить за всеми другими атрибутами в основном классе.


Теперь я думаю, что лучшим подходом было бы создание крошечного класса, который бы содержал только мьютекс и критические атрибуты. Затем я могу написать конструктор уменьшенной копии и оператор присваивания для критического класса и оставить компилятору следить за всеми другими атрибутами в основном классе.
class cSafe {
  boost::mutex myMutex;
  cSomeClass A;
public:
  cSomeClass getA() {
    boost::mutex::scoped_lock lock( myMutex );
    return A;
  }
  (copy constructor)
  (assignment op )

};
class cMyClass {
  cSafe S;
  ( ... other attributes ... )
public:
  cSomeClass getA() {
    return S.getA();
  }
};
9
задан ravenspoint 22 February 2011 в 00:09
поделиться