У меня есть класс, который имеет состояние (простое перечисление) и доступно из двух потоков. Для изменения состояния я использую мьютекс (boost:: mutex). Безопасно ли проверять состояние (например, compare state_ == ESTABLISHED) или мне нужно использовать мьютекс в этом случае? Другими словами, нужен ли мне мьютекс, когда я просто хочу прочитать переменную, которая может быть одновременно записана другим потоком?
Нужен ли мне мьютекс для чтения?
Ответ 1
Это зависит.
Язык С++ ничего не говорит о потоках или атомарности.
Но на большинстве современных процессоров чтение целого числа является атомной операцией, что означает, что вы всегда будете читать согласованное значение, даже без мьютекса.
Однако, без мьютекса или какой-либо другой формы синхронизации, компилятор и процессор могут свободно изменять порядок чтения и записи, поэтому все более сложное, что связано с доступом к нескольким переменным, по-прежнему небезопасно в общий случай.
Предполагая, что поток писателя обновляет некоторые данные, а затем устанавливает флаг целого, чтобы информировать другие потоки, что данные доступны, это может быть переупорядочено, поэтому флаг устанавливается перед обновлением данных. Если вы не используете мьютекс или другую форму барьера памяти.
Итак, если вы хотите правильного поведения, вам не нужен мьютекс как таковой, и это не проблема, если другой поток пишет эту переменную во время ее чтения. Это будет атомный, если вы не работаете с очень необычным процессором. Но вам do нужен какой-либо барьер памяти, чтобы предотвратить переупорядочение в компиляторе или процессоре.
Ответ 2
У вас есть два потока, они обмениваются информацией, да вам нужен мьютекс, и вам, вероятно, также потребуется условное ожидание.
В вашем примере (ср. state_ == ESTABLISHED) указывает, что поток # 2 ожидает, что нить # 1 инициирует соединение/состояние. Без мьютекса или условных выражений/событий поток # 2 должен постоянно отслеживать состояние.
Потоки используются для повышения производительности (или повышения отзывчивости), опрос обычно приводит к снижению производительности, либо за счет использования большого количества процессоров, либо путем введения латентного за счет интервала опроса.
Ответ 3
Да. Если thread a читает переменную, а поток b записывает ее, вы можете прочитать значение undefined. Операция чтения и записи не является атомарной, особенно в многопроцессорной системе.
Ответ 4
Вообще говоря, вы этого не делаете, если ваша переменная объявлена с помощью "volatile". И ТОЛЬКО, если это единственная переменная - иначе вы должны быть очень осторожны в возможных гонках.
Ответ 5
Доступ к перечислению (чтение или запись) должен быть защищен.
Другое дело: Если конфликт потоков меньше, и потоки принадлежат одному процессу, то критический раздел будет лучше, чем мьютекс.
Ответ 6
на самом деле, нет причин блокировать доступ к объекту для чтения. вы только хотите заблокировать его во время записи. это именно то, что блокирует читатель-писатель. он не блокирует объект, если нет операций записи. он повышает производительность и предотвращает взаимоблокировки. см. следующие ссылки для более подробных объяснений: