Rust内存重排问题验证:操作顺序与原子序影响
fn do_something_under_lock( is_locked: &AtomicBool, some_atomic_counter_1: &AtomicUsize, some_atomic_counter_2: &AtomicUsize, ) { read_and_write_non_atomic_memory_1_before_lock(); read_and_write_non_atomic_memory_2_before_lock(); some_atomic_counter_1.fetch_add(1, Ordering::Relaxed); some_atomic_counter_2.fetch_add(1, Ordering::Relaxed); let mut succeeded_acquire; loop { succeeded_acquire = is_locked .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed) .is_ok(); if succeeded_acquire { read_and_write_non_atomic_memory_1_inside_lock(); some_atomic_counter_1.fetch_add(2, Ordering::Relaxed); is_locked.store(false, Ordering::Release); break; } } read_and_write_non_atomic_memory_1_after_lock(); read_and_write_non_atomic_memory_2_after_lock(); some_atomic_counter_1.fetch_add(3, Ordering::Relaxed); some_atomic_counter_2.fetch_add(3, Ordering::Relaxed); }
- 当函数被内联时,
read_and_write_non_atomic_memory_1_before_lock();是否可以被重排到do_something_under_lock调用之前?
可以,直到遇到原子
Acquire操作(因为Acquire会阻止操作被重排到自身之前)或针对同一内存的非原子操作(否则会破坏单线程逻辑)
read_and_write_non_atomic_memory_1_before_lock();是否可以被重排到原子Acquire操作之后?
可以,因为原子
Acquire不会阻止编译器将操作重排到自身之后
read_and_write_non_atomic_memory_1_before_lock();是否可以被重排到read_and_write_non_atomic_memory_1_inside_lock();之后?
不可以,因为这些操作针对同一内存,必须保持代码中的执行顺序,否则会破坏单线程逻辑
read_and_write_non_atomic_memory_1_inside_lock();是否可以被重排到原子Release操作之后?
不可以,因为原子
Release会阻止这种重排
read_and_write_non_atomic_memory_1_after_lock();是否可以被重排到Release操作之前?
可以,因为原子
Release不会阻止操作被重排到自身之前
read_and_write_non_atomic_memory_1_after_lock();是否可以被重排到read_and_write_non_atomic_memory_1_inside_lock();之前?
不可以,因为这些操作针对同一内存,必须保持代码中的执行顺序,否则会破坏单线程逻辑
- 当函数被内联时,
read_and_write_non_atomic_memory_2_before_lock();是否可以被重排到do_something_under_lock调用之前?
可以,直到遇到原子
Acquire操作(因为Acquire会阻止操作被重排到自身之前)或针对同一内存的非原子操作(否则会破坏单线程逻辑)
read_and_write_non_atomic_memory_2_before_lock();是否可以被重排到read_and_write_non_atomic_memory_1_before_lock();之前?
可以,因为这些操作针对不同内存,且两者之间没有原子
Acquire或Release操作
read_and_write_non_atomic_memory_2_before_lock();是否可以被重排到原子Acquire操作之后?
可以,因为原子
Acquire不会阻止编译器将操作重排到自身之后
read_and_write_non_atomic_memory_2_before_lock();是否可以被重排到原子Release操作之后?
不可以,因为原子
Release会阻止这种重排
read_and_write_non_atomic_memory_2_after_lock();是否可以被重排到Release操作之前?
可以,因为原子
Release不会阻止操作被重排到自身之前
read_and_write_non_atomic_memory_2_after_lock();是否可以被重排到Acquire操作之前?
不可以,因为原子
Acquire会阻止操作被重排到自身之前
- 当函数被内联时,
some_atomic_counter_1.fetch_add(1, Ordering::Relaxed);是否可以被重排到do_something_under_lock调用之前?
可以,直到遇到原子
Acquire操作(因为Acquire会阻止操作被重排到自身之前)或针对同一原子内存的操作(否则会破坏单线程逻辑)
some_atomic_counter_1.fetch_add(1, Ordering::Relaxed);是否可以被重排到原子Acquire操作之后?
可以,因为原子
Acquire不会阻止编译器将操作重排到自身之后
some_atomic_counter_1.fetch_add(1, Ordering::Relaxed);是否可以被重排到some_atomic_counter_1.fetch_add(2, Ordering::Relaxed);之后?
不可以,因为这些操作针对同一内存,必须保持代码中的执行顺序,否则会破坏单线程逻辑
some_atomic_counter_1.fetch_add(2, Ordering::Relaxed);是否可以被重排到原子Release操作之后?
不可以,因为原子
Release会阻止这种重排
some_atomic_counter_1.fetch_add(3, Ordering::Relaxed);是否可以被重排到Release操作之前?
可以,因为原子
Release不会阻止操作被重排到自身之前
some_atomic_counter_1.fetch_add(3, Ordering::Relaxed);是否可以被重排到some_atomic_counter_1.fetch_add(2, Ordering::Relaxed);之前?
不可以,因为这些操作针对同一内存,必须保持代码中的执行顺序,否则会破坏单线程逻辑
- 当函数被内联时,
some_atomic_counter_2.fetch_add(1, Ordering::Relaxed);是否可以被重排到do_something_under_lock调用之前?
可以,直到遇到原子
Acquire操作(因为Acquire会阻止操作被重排到自身之前)或针对同一原子内存的操作(否则会破坏单线程逻辑)
some_atomic_counter_2.fetch_add(1, Ordering::Relaxed);是否可以被重排到some_atomic_counter_1.fetch_add(1, Ordering::Relaxed);之前?
可以,因为这些操作针对不同内存,且两者之间没有原子
Acquire或Release操作
some_atomic_counter_2.fetch_add(1, Ordering::Relaxed);是否可以被重排到原子Acquire操作之后?
可以,因为原子
Acquire不会阻止编译器将操作重排到自身之后
some_atomic_counter_2.fetch_add(1, Ordering::Relaxed);是否可以被重排到原子Release操作之后?
不可以,因为原子
Release会阻止这种重排
some_atomic_counter_2.fetch_add(3, Ordering::Relaxed);是否可以被重排到Release操作之前?
可以,因为原子
Release不会阻止操作被重排到自身之前
some_atomic_counter_2.fetch_add(3, Ordering::Relaxed);是否可以被重排到Acquire操作之前?
不可以,因为原子
Acquire会阻止操作被重排到自身之前
- 若将以下代码中的
Acquire改为Relaxed,会产生什么影响?
succeeded_acquire = is_locked .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed) .is_ok();
编译器不会指示CPU从全局内存加载最新的内存变更到本地核心缓存,可能使用陈旧内存,导致
read_and_write_non_atomic_memory_1_inside_lock();出现竞态
- 若将以下代码中的
Release改为Relaxed,会产生什么影响?
is_locked.store(false, Ordering::Release);
编译器不会指示CPU将本地核心缓存的内存变更同步到全局内存,其他核心可能使用陈旧内存,导致
read_and_write_non_atomic_memory_1_inside_lock();出现竞态
内容的提问来源于stack exchange,提问作者Ivan Ivanyuk

