мьютекс как член класса

#c #multithreading #boost #mutex

#c #многопоточность #повышение #мьютекс

Вопрос:

  class temp
 {
    boost::mutex mx;
    void CriticalCode() {
        boost::mutex::scoped_lock scoped_lock(mx); 
        //Do Something
        return;
    }
 }
  
  1. Если этот класс размещен в куче ( temp* T = new temp() ), будет ли это потокобезопасным (для каждого экземпляра, а не для всех экземпляров вместе)?

  2. Если я создам boost::mutex mx -> boost::mutex* mx и выделю его в конструкторе, чтобы он был размещен в куче, будет ли код также потокобезопасным?

  3. Если ответы на 1 и 2 отрицательные, как я могу сделать потокобезопасным каждый экземпляр?

Комментарии:

1. Почему люди говорят о «стеке» и «куче», когда они могут говорить об «автоматическом» и «динамическом» распределении.

2. в пункте 2 в этом нет абсолютно никакой необходимости. ЕДИНСТВЕННОЙ причиной сделать его указателем (и даже тогда я бы сделал его ссылкой) было бы передать мьютекс экземпляру во время построения — т. Е. У вас есть один мьютекс, который вы хотите использовать для всех экземпляров.

Ответ №1:

1) если этот класс выделен в куче (temp* T = new temp()) , будет ли это потокобезопасным (для каждого экземпляра, а не для всех экземпляров вместе?

ДА. Поскольку mx не является статическим членом класса, для каждого экземпляра класса будет установлена одна блокировка.

2) если я создам boost:: mutex mx -> boost::mutex * mx и выделю его в конструкторе, чтобы он был размещен в куче, будет ли код также потокобезопасным?

ДА. Но потокобезопасен только для каждого экземпляра.

3) если теперь дан ответ на 1 и 2, как я могу сделать потокобезопасным каждый экземпляр?

Ответы «да», так что все в порядке.

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

Комментарии:

1. Что касается вашего последнего комментария, это сильно зависит от того, где и как создается статический экземпляр (т.е. lazy по своей сути не является потокобезопасным!). Если вы в конечном итоге выберете этот подход — вам ДЕЙСТВИТЕЛЬНО нужно пересмотреть свой дизайн.

2. Я понимаю. Я не в курсе ленивых статических переменных. Ученый-компьютерщик во мне говорит мне, что термин подразумевает, что выделение не выполняется до тех пор, пока переменная фактически не будет записана. Для меня это все еще звучит потокобезопасно, но, возможно, я что-то упускаю, не могли бы вы рассказать мне больше?

3. существует два способа использования статики в данном классе. Один из способов — объявить их непосредственно как статические члены, а затем фактически определить их в модуле трансляции (проблема здесь в том, что вы тогда зависите от порядка инициализации — и это не гарантируется). Обходным путем для этого является объявление объекта как статического в статической функции класса и возврат ссылки на этот статический экземпляр — это отложенная инициализация, о которой я говорил. Однако это по своей сути не является потокобезопасным (стандарт ничего не указывает на потоковую обработку и, следовательно, на то, кто создает).

4. …т.е. если два потока вводят статическую функцию, чтобы получить блокировку, и никто раньше не вызывал эту функцию, нет никакой гарантии относительно того, кто создает. Одним из способов обойти это было бы провести некоторую глобальную инициализацию перед созданием потоков, которая вызывает эту статическую функцию для создания мьютекса… Другой вариант — просто передать мьютекс при создании temp объекта и иметь только ссылку на мьютекс в temp .

Ответ №2:

Местоположение хранилища не имеет ни к чему отношения.

Ответ №3:

Да, метод CriticalCode() будет потокобезопасным в обоих случаях.