synchronizes-with

两个线程A,B, 以及一个支持原子操作的变量X,如果A线程对X store了一个新的值,B线程在X上读到了新的值,那就可以说A的store synchronize-with B 的 load

happens-before

如果一个操作B能看到之前操作A产生的结果,那么A就是happens-before B, 例如在一个线程中,操作A的语句在B之前执行,那么A happens-before B

Relaxed ordering

保证原子操作,在同一个线程中,对同一个变量的操作满足happens-before, 但跨线程操作中,不能保证顺序

  1. fn write_x_then_y() {
  2. X.store(true, Ordering::Relaxed);
  3. Y.store(true, Ordering::Relaxed);
  4. }
  5. fn read_y_then_x() {
  6. while !Y.load(Ordering::Relaxed) {}
  7. if X.load(Ordering::Relaxed){
  8. Z.fetch_add(1, Ordering::SeqCst);
  9. }
  10. }
  11. fn main() {
  12. let t1 = thread::spawn(move || {
  13. write_x_then_y();
  14. });
  15. let t2 = thread::spawn(move || {
  16. read_y_then_x();
  17. });
  18. t1.join().unwrap();
  19. t2.join().unwrap();
  20. assert_ne!(Z.load(Ordering::SeqCst), 0);
  21. }

write_x_then_y 中,Y store happens-before X store, 但是由于Relax 并不保证sync-with,所以load可能看到的是乱序的store

Acquire-Release ordering

release

release updates we’ve made to memory, “publish” to other threads.

acquire

acquire memory published by other threads, making it avaliable to us.

image.png

image.png
image.png

  1. threadA store a,b 两个variable,这个时候都保存在A线程的内存中,对于其他线程都不可见
  2. threadA release store c, 将c publish到主内存中,同时a,b两个变量也同步到了主内存
  3. threadB, acquire load c,将c从主内存中,同步到B线程中,同时将a,b两个变量也同步到了 threadB

Acquire和release 成对使用,当store使用Release ordering后,后续的Acquire ordering的load操作,都会看到之前的store值,他是sync-with

  1. fn write_x_then_y() {
  2. X.store(true, Ordering::Relaxed);
  3. Y.store(true, Ordering::Release);
  4. }
  5. fn read_y_then_x() {
  6. while !Y.load(Ordering::Acquire){}
  7. if X.load(Ordering::Relaxed) {
  8. Z.fetch_add(1, Ordering::SeqCst);
  9. }
  10. }
  11. fn main() {
  12. let t1 = thread::spawn(move || {
  13. write_x_then_y();
  14. });
  15. let t2 = thread::spawn(move || {
  16. read_y_then_x();
  17. });
  18. t1.join().unwrap();
  19. t2.join().unwrap();
  20. assert_ne!(Z.load(Ordering::SeqCst), 0);
  21. }

Y.load(Ordering::Acquire) Y.store(true, Ordering::Release); 表明线程t1, t2对于Y是syn-with的,并且由于happened-before, X store 保证在Y store之前,X load保证在Y load之后,所以X load X store 虽然是relaxed, 但也保证了顺序

AcqRel

is used to reads the value but also wirtes the value, like fetch_and _add, usually used in doing a single modifation operation

Sequence ordering

保证所有线程会看到完全一致的原子操作顺序