Тип memory_order
Тип memory_order используется для указания того, как атомарные операции
должны взаимодействовать с памятью. Он определяет, какие переупорядочивания
инструкций разрешены компилятору и процессору. Существует шесть значений
этого перечисления: memory_order_relaxed, memory_order_consume,
memory_order_acquire, memory_order_release,
memory_order_acq_rel и memory_order_seq_cst.
Каждое значение задает свои правила синхронизации и порядок видимости
изменений для других потоков.
Синтаксис
enum memory_order {
memory_order_relaxed,
memory_order_consume,
memory_order_acquire,
memory_order_release,
memory_order_acq_rel,
memory_order_seq_cst
};
Пример
Давайте рассмотрим использование memory_order_relaxed для
атомарного счетчика. Этот порядок не гарантирует синхронизацию,
но обеспечивает атомарность операций:
#include <iostream>
#include <atomic>
#include <thread>
using namespace std;
atomic<int> counter(0);
void increment()
{
for (int i = 0; i < 1000; ++i) {
counter.fetch_add(1, memory_order_relaxed);
}
}
int main()
{
thread t1(increment);
thread t2(increment);
t1.join();
t2.join();
cout << counter.load() << endl;
return 0;
}
Результат выполнения кода:
2000
Пример
Давайте рассмотрим использование memory_order_acquire и
memory_order_release для синхронизации между потоками.
Поток-писатель устанавливает флаг, а поток-читатель ждет его:
#include <iostream>
#include <atomic>
#include <thread>
using namespace std;
atomic<bool> ready(false);
int data = 0;
void producer()
{
data = 42;
ready.store(true, memory_order_release);
}
void consumer()
{
while (!ready.load(memory_order_acquire)) {
// wait
}
cout << data << endl;
}
int main()
{
thread t1(producer);
thread t2(consumer);
t1.join();
t2.join();
return 0;
}
Результат выполнения кода:
42