Какие-нибудь недостатки для std::atomic_flag, не обеспечивающего операции загрузки или хранения? (Пример Spin-Lock)
Сравнивая std::atomic_flag
для std::atomic_bool
(ака std::atomic<bool>
мне кажется, что std::atomic_flag
просто имеет более простой интерфейс. Он обеспечивает только тестирование + установку и очистку флага во время std::atomic_bool
также обеспечивает перегрузки для нескольких операторов.
Один мой вопрос касается терминологии: что подразумевается под "операциями загрузки или хранения"? Означает ли это, что невозможно произвольно прочитать и изменить std::atomic_flag
ценность?
Кроме того, мне интересно, std::atomic_bool
Быть быстрее, когда используется для спин-блокировки? Мне кажется, что std::atomic_flag
всегда должен читать и писать во время спин-блокировки:
while (my_atomic_flag.test_and_set()); // spin-lock
в то время как std::atomic_bool
нужно будет только выполнить операцию чтения (при условии, что атомарный тип bool реализован без блокировки):
while (my_atomic_bool); // spin-lock
Является std::atomic_flag
строго эффективнее, чем std::atomic_bool
или это может быть наоборот? Что следует использовать для спин-блокировки?
1 ответ
Что подразумевается под "операциями загрузки или хранения"? Означает ли это, что невозможно произвольно прочитать и изменить значение std::atomic_flag?
Обычные операции сохранения / загрузки не поддерживаются std::atomic_flag
,
Это тип только для модификации; то есть. вы не можете прочитать доступ std::atomic_flag
объект без выполнения модифицирующей операции.
В общем, std::atomic_flag
подразумевается как строительный блок для других операций. Его интерфейс преднамеренно прост; это единственный атомарный тип, который имеет гарантированные атомарные операции без блокировки. Поддерживаемые операции:
std::atomic_flag::clear()
std::atomic_flag::test_and_set()
При этом вы можете легко создать свой собственный спинлок (хотя обычно это не рекомендуется):
class my_spinlock {
std::atomic_flag flag = ATOMIC_FLAG_INIT;
public:
void lock()
{
while(flag.test_and_set());
}
void unlock()
{
flag.clear();
}
};
Кроме того, мне интересно, может ли std::atomic_bool быть быстрее при использовании для спин-блокировки? Мне кажется, что std::atomic_flag всегда должен читать и писать во время спин-блокировки
Что ж, дело в том, что спин-блокировка всегда должна изменять свое состояние при получении блокировки. Вы просто не можете взломать замок, не сказав об этом другим.
Реализация для lock()
основанный на std::atomic<bool>
выглядит очень похоже:
while (flag.exchange(true));
Будь спинлок на основе std::atomic_flag
быстрее?
На моей платформе компилятор выдает одинаковую сборку для обоих типов, поэтому я был бы очень удивлен.