Мне нравится думать о синхронизации потоков как о том, что процессор и операционная система обеспечивают конструкцию, примитивную для более сложных
На уровне процессора у вас есть CAS и LL / SC, которые позволяют вам выполнять тестирование и сохранять в одной атомарной операции ... у вас также есть другие конструкции процессора, которые позволяют вам отключать и включать прерывания (какими бы они ни считались опасно ... при определенных обстоятельствах у вас нет другого выбора, кроме как использовать их)
операционная система предоставляет возможность переключения контекста между задачами, которые могут происходить каждый раз, когда поток использует свой временной интервал ... или это может происходить по другим причинам (я вернусь к этому)
тогда существуют конструкции более высокого уровня, такие как мьютексы, которые используют эти примитивные механизмы, предоставляемые процессором (например, вращающийся мьютекс) ... которые будут непрерывно ждать, пока условие станет истинным, и атомно проверять это условие
тогда этот вращающийся мьютекс может использовать функциональность, предоставляемую ОС (переключение контекста и системные вызовы, такие как yield, который передает управление другому потоку) и дает нам мьютексы
эти конструкции используются в дальнейшем конструкциями более высокого уровня, такими как условные переменные (которые могут отслеживать, сколько потоков ожидает мьютекс и какой поток разрешить первым, когда мьютекс станет доступным)
Эти конструкции могут использоваться для обеспечения более сложных конструкций синхронизации ... пример: семафоры и т. Д.