Нужен ли мьютекс для чтения? - PullRequest
38 голосов
/ 06 октября 2009

У меня есть класс, который имеет состояние (простое перечисление) и доступ к нему из двух потоков. Для изменения состояния я использую мьютекс (boost :: mutex). Безопасно ли проверять состояние (например, сравнивать state_ == ESTABLISHED) или мне также нужно использовать мьютекс в этом случае? Другими словами, нужен ли мне мьютекс, когда я просто хочу прочитать переменную, которая может быть одновременно записана другим потоком?

Ответы [ 6 ]

19 голосов
/ 13 октября 2009

Это зависит.

Язык C ++ ничего не говорит о потоках или атомарности.

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

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

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

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

9 голосов
/ 06 октября 2009

У вас есть два потока, они обмениваются информацией, да, вам нужен мьютекс, и вам, вероятно, также необходимо условное ожидание.

В вашем примере (сравните состояние_ == ESTABLISHED) указывает, что поток № 2 ожидает, пока поток № 1 инициирует соединение / состояние. Без мьютекса или условных / событий поток № 2 должен непрерывно опрашивать статус.

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

2 голосов
/ 06 октября 2009

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

1 голос
/ 13 октября 2009

на самом деле нет никаких оснований блокировать доступ к объекту для чтения. Вы хотите заблокировать его только во время записи. это именно то, что блокировка читателя-писателя. это не блокирует объект, пока нет никаких операций записи. это повышает производительность и предотвращает взаимные блокировки. см. следующие ссылки для более подробных объяснений:

википедии CodeProject

1 голос
/ 06 октября 2009

Вообще говоря, нет, если ваша переменная объявлена ​​как "volatile". И ТОЛЬКО если это одна переменная - иначе вы должны быть очень осторожны с возможными гонками.

0 голосов
/ 06 октября 2009

Доступ к перечислению (чтение или запись) должен быть защищен.

Другое дело: Если конкуренция за поток меньше и потоки принадлежат одному и тому же процессу, тогда критический раздел будет лучше, чем мьютекс.

...