Многопоточность C : нужен ли мне мьютекс для конструктора и деструктора?

#c #multithreading

#c #многопоточность

Вопрос:

Для объекта, к которому будут обращаться несколько потоков, нужно ли мне иметь мьютекс для его конструктора и деструктора?

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

С другой стороны, я не могу придумать причину, по которой нам нужен мьютекс в конструкторе, поскольку другие потоки не могут получить доступ к объекту до того, как он будет полностью сконструирован.

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

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

2. когда объект создается или уничтожается, он должен использоваться только одним потоком, иначе возникает большая логическая проблема. Таким образом, вам не нужно синхронизировать ctor и dtor. В этом нет никакого смысла. Единственная синхронизация, которая имеет смысл, — это объединение потоков, порожденных этим объектом.

3. Если есть поток, ожидающий доступа к объекту, который находится в процессе деинициализации, я бы назвал это ошибкой.

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

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

Ответ №1:

Вы не можете предоставить общий доступ к объекту до его создания. Если он не является общим, то его использует только один поток. Вывод нет необходимости синхронизировать что-либо в constructor (если только вы не создаете новый поток).

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

Если по какой-то волшебной причине у вас будет состояние гонки в конструкторе или деструкторе, ошибка должна быть в владельце объекта.

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

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

1. «Вы не можете предоставить общий доступ к объекту до его создания» — это действительно так? Есть ли гарантия, что назначение поля и публикация указателя объекта имеют одинаковый порядок с точки зрения другого потока в отсутствие синхронизации?

2. вы смешиваете обязанности. В случае, если вы описываете, за синхронизацию отвечает код, который создает объект, а не сам объект. Race находится не на заданном уровне класса, а на уровне, который использует этот класс. Классический пример shared_ptr , его внутренние данные (счетчик ссылок) потокобезопасны, но вам придется синхронизировать переменную, если вы ее измените.

3. Тем не менее, «невозможно» — довольно сильное утверждение. «Должен делиться безопасным способом, но это работа любого другого», возможно, было бы более точным. Но даже если это так, то у нас есть защита указателя объекта с помощью мьютекса указателя объекта и защита состояния объекта с помощью другого мьютекса, а инициализация объекта не защищена никаким мьютексом, разве это не гонка данных и, следовательно, UB?

4. Пожалуйста, приведите пример, где это может произойти. Случаи, которые я могу себе представить, и это могло бы произойти, настолько экстремальны и странны, что их не стоит рассматривать (для меня они пахнут кодом). Обратите внимание также, что если вы можете запустить race в конструкторе, то вы можете столкнуться с ситуацией, когда мьютекс (который должен быть частью объекта) еще не создан, и это означает, что нет инструмента для синхронизации. В любом случае для меня EOT, поскольку мы начинаем спорить. Есть высказывание: «Если вы спорите, вы проигрываете».