Тип AtomicBool
Тип AtomicBool - это атомарный логический тип из модуля
std::sync::atomic. Он хранит значение типа bool
и позволяет нескольким потокам одновременно читать и изменять
это значение без блокировок и без риска гонки данных. Все операции
над AtomicBool выполняются атомарно, то есть одна операция
не может быть прервана другой операцией из другого потока.
Тип параметризуется значением порядка доступа Ordering,
которое определяет, как операции с памятью упорядочиваются
относительно других потоков. Основные методы типа:
new, load, store, swap,
compare_exchange, fetch_and, fetch_or,
fetch_xor и get_mut.
Синтаксис
use std::sync::atomic::AtomicBool;
use std::sync::atomic::Ordering;
let flag = AtomicBool::new(false);
let value = flag.load(Ordering::Relaxed);
flag.store(true, Ordering::Relaxed);
Пример
Давайте создадим атомарный флаг и прочитаем его значение:
use std::sync::atomic::AtomicBool;
use std::sync::atomic::Ordering;
fn main()
{
let flag = AtomicBool::new(false);
let res = flag.load(Ordering::Relaxed);
println!("{}", res);
}
Результат выполнения кода:
false
Пример
Давайте изменим значение флага с помощью метода store
и затем прочитаем его:
use std::sync::atomic::AtomicBool;
use std::sync::atomic::Ordering;
fn main()
{
let flag = AtomicBool::new(false);
flag.store(true, Ordering::Relaxed);
let res = flag.load(Ordering::Relaxed);
println!("{}", res);
}
Результат выполнения кода:
true
Пример
Давайте используем метод swap, который заменяет значение
и возвращает предыдущее:
use std::sync::atomic::AtomicBool;
use std::sync::atomic::Ordering;
fn main()
{
let flag = AtomicBool::new(false);
let old = flag.swap(true, Ordering::Relaxed);
println!("old: {}", old);
println!("new: {}", flag.load(Ordering::Relaxed));
}
Результат выполнения кода:
old: false
new: true
Пример
Давайте используем метод compare_exchange для замены
значения только в том случае, если оно равно ожидаемому:
use std::sync::atomic::AtomicBool;
use std::sync::atomic::Ordering;
fn main()
{
let flag = AtomicBool::new(false);
let res = flag.compare_exchange(
false,
true,
Ordering::Relaxed,
Ordering::Relaxed
);
println!("{:?}", res);
println!("{}", flag.load(Ordering::Relaxed));
}
Результат выполнения кода:
Ok(false)
true
Пример
Давайте разделим атомарный флаг между двумя потоками. Один поток будет устанавливать флаг, а другой - читать его:
use std::sync::Arc;
use std::sync::atomic::AtomicBool;
use std::sync::atomic::Ordering;
use std::thread;
fn main()
{
let flag = Arc::new(AtomicBool::new(false));
let flag_clone = Arc::clone(&flag);
let handle = thread::spawn(move || {
flag_clone.store(true, Ordering::Relaxed);
});
handle.join().unwrap();
let res = flag.load(Ordering::Relaxed);
println!("{}", res);
}
Результат выполнения кода:
true
Смотрите также
-
тип
AtomicUsize,
который представляет атомарное беззнаковое целое -
тип
AtomicI32,
который представляет атомарное знаковое целое -
перечисление
Ordering,
которое задаёт порядок доступа к памяти -
тип
Once,
который гарантирует однократное выполнение инициализации