rustatomicmemory-barriersinstruction-reordering

Relaxed Memory ordering on fetch_add


I'm going through Mara's Atomics and locks book, which shows this example code where it assumes that the function a and b are executed concurrently:

static X: AtomicI32 = AtomicI32::new(0);

fn a() {
    X.fetch_add(5, Relaxed);
    X.fetch_add(10, Relaxed);
}

fn b() {
    let a = X.load(Relaxed);
    let b = X.load(Relaxed);
    let c = X.load(Relaxed);
    let d = X.load(Relaxed);
    println!("{a} {b} {c} {d}");
}

Ref: https://marabos.nl/atomics/memory-ordering.html#relaxed

It says that since only one thread modifies X, only one possible order of modification of X is possible: 0 -> 5 -> 15

My question is why it cannot be this instead: 0 -> 10 -> 15 because of the possiblity of reordering of instruction ? I ask this because earlier in this chapter this was specified:

The logic for verifying that a specific reordering or other optimization won’t affect the behavior of your program does not take other threads into account.

Because of that, I belive the compiler or processor is free to optimize and re-reorder if required.


Solution

  • There's reordering and there's reordering :)

    Atomic instructions on a single atomic values are always ordered, regardless of the memory ordering used.

    The memory ordering only affects the ordering of memory operations on other values (atomic or not) relatively to the atomic operation.