Atomic

2024-06-01

最后编辑于:2024-09-13

    #Rust
    #concurrency

提供了能在线程间使用的共享内存类型 为基本类型提供了原子版本 AtomicBool,AtomicUsize,AtomicI8,AtomicU16,etc. 在正确使用时,更改会在线程间同步

原子访问的内存模型

目前使用和C++20 atomics一样的规则

每个方法接受一个Ordering,代表该操作内存屏障的强度 OrderingRelease,Acquire,Relaxed,SeqCst,AcqRel

Relaxed

最弱的内存序,表示对这次操作没有任何同步或者顺序的要求。这种方式只保证原子操作的读写不会被重排序。

Acquire/Release

Acquire/Relase通常配合使用,用于在线程间传递数据。

  • Acquire用于原子操作的读取部分,保证在此操作之后的所有内存读写不能被重排序到这个操作之前。通常用于加载操作。
  • Release用于原子操作的写入部分,保证在此操作之前的所有内存读写不能被重排序到这个操作之后。通常用于存储操作。
let ready = AtomicBool::new(false);

let producer = thread::spawn(move || {
	ready.store(true, Ordering::Release);
});

let consumer = thread::spawn(move || {
	while !read.load(Ordering::Acquire) {
		// waiting for data
	}
	// use data
});

SeqCst

最强的内存序,代表顺序一致性(Sequential Consistency)。这种方式要求保证所有原子操作都按照程序的书写顺序执行。

AcqRel

Acquire/Release的结合 常用于读-修改-写操作,如(fetch_add, compare_and_swap)

let atomic_counter = AtomicUsize::new(0);

let mut handles = vec![];
for _ in 0..10 {
	let handle = thread::spawn(move || {
		let counter = &atomic_counter;
		move || {
			for _ in 0..10 {
				counter.fetch_add(1, Ordering::AcqRel);
			}
		}
	});
	handles.push(handle);
}

https://doc.rust-lang.org/std/sync/atomic/ https://doc.rust-lang.org/nomicon/atomics.html