Требуется ли для получения спин-блокировки сравнение-своп или достаточно свопа?
Предположим, у нас есть spinlock
реализация:
struct Lock {
locked : Atomic(bool),
}
Тогда функция разблокировки может быть:
fun unlock(lock : &Lock) {
atomic_store(&lock.locked, false, release);
}
Но что насчет lock
? Как правило, он использует сравнение и обмен, как это:
fun lock(lock : &Lock) {
while atomic_compare_and_swap(&lock.locked, false, true, acquire) {}
}
Но разве для этого не будет достаточно свопа? Что-то вроде этого:
fun lock(lock : &Lock) {
while atomic_swap(&lock.locked, true, acquire) {}
}
Есть ли проблемы с этим?
1 ответ
Сравнение и обмен не являются действительно необходимыми. Атомная установка флага true
если это false
логически эквивалентно безусловной установке его true
,
Безусловный обмен может быть немного быстрее, поскольку не нужно ничего сравнивать, хотя реальная стоимость атомарной операции чтения-изменения-записи заключается в получении и блокировке строки кэша.
Вот пример C++ спинлока, который использует exchange()
#include <atomic>
class mutex {
std::atomic<bool> flag{false};
public:
void lock()
{
while (flag.exchange(true, std::memory_order_acquire));
}
void unlock()
{
flag.store(false, std::memory_order_release);
}
};