В многопоточном приложении C ++ мне нужен мьютекс для защиты простого логического значения? - PullRequest
14 голосов
/ 21 октября 2008

У меня есть многопоточное приложение C ++, которое выполняет 3D-рендеринг с помощью библиотеки OpenSceneGraph. Я планирую запустить цикл рендеринга OSG как отдельный поток, используя boost :: threads, передавая структуру данных, содержащую разделяемое состояние, в поток. Я стараюсь избегать чего-либо слишком тяжелого (например, мьютексов) для синхронизации, поскольку цикл рендеринга должен быть довольно узким, а сама OSG старается избегать блокировки. Большая часть общего состояния устанавливается до запуска потока и никогда не изменяется. У меня есть некоторые данные, которые нужно изменить, и я планирую создать двойной буфер. Тем не менее, у меня есть простое логическое значение для оповещения потока о приостановке рендеринга, последующего возобновления рендеринга и другого для его прекращения. В обоих случаях поток приложения устанавливает bool, а поток визуализации только читает его. Нужно ли синхронизировать доступ к этим bools? Насколько я могу судить, хуже всего может быть то, что цикл рендеринга продолжается для дополнительного кадра перед приостановкой или выходом.

Ответы [ 5 ]

14 голосов
/ 21 октября 2008

В C ++ 11 и более поздних версиях, в которых есть определенный параллелизм, используйте std::atomic<bool> для этой цели. От http://en.cppreference.com/w/cpp/atomic/atomic:

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


Следующий старый ответ мог быть верным в прошлом в некоторых компиляторах и в некоторых операционных средах, но на него не следует полагаться сегодня:

Вы правы, в этом случае вам не нужно синхронизировать bool. Однако вы должны объявить их volatile, чтобы компилятор действительно каждый раз считывал их из памяти, вместо того, чтобы кэшировать предыдущее чтение в потоке (это упрощенное объяснение, но для этого следует). 1015 * Следующий вопрос содержит более подробную информацию об этом: C ++ Thread, общие данные

7 голосов
/ 21 октября 2008

Почему бы просто не использовать блокированную переменную ?

4 голосов
/ 18 декабря 2017

Что касается C ++ 11 и более поздних версий, он, наконец, учитывает потоки и четко заявляет, что изменение bool (или другой неатомарной переменной) в одном потоке и одновременный доступ к нему в другом является неопределенным поведением. В вашем случае использования std::atomic<bool> должно быть достаточно для исправления вашей программы, избавляя вас от использования блокировок.
Не использовать volatile. Это не имеет ничего общего с потоками. Для более подробного обсуждения смотрите Могу ли я прочитать переменную bool в потоке без мьютекса?

3 голосов
/ 21 октября 2008

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

Вы должны изучить использование различных примитивов обмена Exchange (InterlockedExchange под Windows). Не потому, что чтение / запись из bool не являются атомарными, но чтобы гарантировать отсутствие странных действий, компилятор переупорядочивает доступ к памяти в одном потоке.

1 голос
/ 21 октября 2008

В этой теме есть немного больше информации и обсуждения безопасности потоков, особенно для простых типов данных:

Как создать потокобезопасный шаблон синглтона в Windows?

...