Меня смущают ограничения, накладываемые политикой выполнения par_unseq
и идеей функций " векторизация небезопасных ".
Я получаю общее представление: par_unseq
политика выполнения позволяет компилятору выполнять векторизацию, поэтому один поток может чередовать инструкции между различными экземплярами функций. Из-за этого использование чего-то вроде мьютекса может привести к тупику из-за переупорядочения команд.
Но как быть с алгоритмами Atom c без блокировки, такими как compare_exchange l oop? Или алгоритмы Atom c без ожидания, такие как механизм подсчета ссылок Atomi c?
Сначала я предположил, что все будет в порядке. Однако в объяснении на cppreference.com говорится:
Неупорядоченные политики выполнения являются единственным случаем, когда вызовы функций не последовательны по отношению друг к другу, то есть они могут чередоваться. Во всех других ситуациях в C ++ они имеют неопределенную последовательность (не могут чередоваться). Из-за этого пользователям не разрешается выделять или освобождать память, приобретать мьютексы, использовать не-lockfree специализации std :: atomi c или вообще выполнять любые небезопасные операции векторизации при использовании этих политик (функции векторизации небезопасных). те, которые синхронизируются с другой функцией, например, std::mutex::unlock
синхронизируются с следующей std::mutex::lock
)
Это сбивает с толку, потому что на с одной стороны, он говорит, что операции без блокировки std::atomic
- это нормально, но с другой стороны, он говорит, что небезопасная векторизация - это любая функция, которая синхронизируется с другой функцией. Термин «синхронизируется с» в стандарте C ++ означает не только мьютексы - это означает любую операцию atomi c, которая синхронизируется с другой, например, загрузку atomi c с использованием std::memory_order_acquire
, которая синхронизируется с atomi c хранить с помощью std::memory_order_release
. Такие операции могут быть без блокировки или без ожидания, но все же синхронизироваться друг с другом, чтобы гарантировать упорядочение между потоками.
Так что можно использовать, например, операции получения / освобождения с блокировкой без std::atomic
переменных (если используемый алгоритм фактически не блокируется, т.е. продвижение вперед гарантируется хотя бы одним потоком)? Или par_unseq
запрещает ЛЮБУЮ синхронизацию вообще (т. Е. Могут безопасно использоваться только расслабленные операции Atom c)?