Мьютексы вокруг одного слова читают и пишут - PullRequest
0 голосов
/ 28 января 2011

Если у вас есть многопоточное приложение с переменной слова, совместно используемой потоками (то есть - 32-битный тип данных в 32-битной системе), необходимо ли защищать чтение и запись в это слово с помощью мьютекса?

Ответы [ 2 ]

2 голосов
/ 28 января 2011

Вместо того, чтобы говорить о кешах, многоядерности, выполнении не по порядку и т. Д. Я просто приведу простой пример, чтобы проиллюстрировать, почему вы хотите использовать мьютекс (или какой-либо другой метод взаимного исключения, например, манипулирование прерываниями). и т. д.)

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

  • Поток B читает «x» из памяти в регистр (значение 5).
  • Поток B увеличивает регистр до значения 6.
  • Нить A упреждает нить B.
  • Поток A считывает «x» в регистр (значение все еще равно 5 в памяти, верно?).
  • Поток A увеличивает регистр до значения 6.
  • Поток A записывает значение 6 обратно в память
  • Нить А засыпает.
  • Поток B просыпается и записывает свое значение регистра 6 обратно в память.

Теперь оба потока увеличили значение, но оно увеличилось только на единицу.

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

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

Примечание: В некоторых случаях - , но не делайте этого - вы можете обойтись без мьютекса, если у вас есть один писатель и несколько читателей. Например, возможно, ISR увеличивает число тиков или что-то в этом роде, и другие потоки / задачи приходят и читают его очень часто.

Полагаю, я хочу подчеркнуть, что это всегда хорошая идея для защиты общих данных , даже если вы думаете, что можете обойтись без них. Если вы хотите «пойти коммандос», вы ДЕЙСТВИТЕЛЬНО должны знать, что вы делаете, и даже тогда тот же код может сломаться завтра, когда он будет перенесен на новую архитектуру.

2 голосов
/ 28 января 2011

В общем, да , вы должны синхронизировать доступ с мьютексом.Даже если вы считаете, что запись в область памяти будет «атомарной», ЦП может переупорядочить инструкции, которые читают и записывают в эту память, вызывая нежелательное поведение.Кроме того, в многоядерной или многоядерной системе запись в общую память может быть не сразу видна другим ядрам / процессорам без синхронизации.

Для получения дополнительной информации см. Статью Википедии для Барьер памяти .

...