javajls

What's the difference between getVolatile and getAcquire?


What is the difference between getVolatile vs getAcquire when using e.g. AtomicInteger?

PS: those are related to

The source of a synchronizes-with edge is called a release, and the destination is called an acquire.

from https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.3


Solution

  • It all comes back to how we want the optimisation of our code. Optimisation in terms of reordering code. Compiler might reorder to optimise. getAcquire ensures that the instructions following it will not be executed before it. These instructions might be reordered but they will always be executed after the getAcquire.

    This works in combination with setRelease (for VarHandle) where setRelease ensures that what happens before it is not reordered to happen after it.

    Example:

    Thread1:
    
        var x = 1;
        var y = 2;
        var z = 3;
    
        A.setRelease(this, 10)
    

    assignments of x, y and z will happen before A.setRelease but might be reordered themselves.

    Thread 2:
    
    if (A.getAcquire(this) == 10) {
      // we know that x is 1, y is 2 and z = 3
    }
    

    This is a nice use case for concurrent program where you don't have to push volatility on everything but just need some instructions to be executed before another.

    For getVolatile, the variable is treated just like any volatile variable in Java. No reordering or optimisation is happening.

    This video is a nice to see to understand whats called the "memory ordering modes" being plain, opaque, release/acquire and volatile.