This is the 4th day of my participation in the August More Text Challenge

The volatile keyword

preface

  • Java uses the keyword volatile to mark Java variables as “main memory access,” which can be interpreted as meaning that each read is written from the computer’s main memory rather than the CPU cache, and each write is written to main memory rather than just the CPU cache.

Volatile features

  • Ensure visibility of variables
  • The forbidden order is rearranged
  • Atomicity is not guaranteed

Variable visibility issues

  • In applications where threads operate on variables that are not decorated with volatile keywords, each thread copies the variables from main memory to the CPU cache for performance reasons. If the computer contains multiple cpus, the threads run on different cpus, meaning that each variable is copied to a different CPU cache.

  • For variables that are not volatile, there is no guarantee when the JVM will read data from main memory or flush it to main memory. This means that when two threads make a variable change at the same time, the actual result is not what we expect, which can also be called a variable visibility problem. For example, thread 1 and thread 2 increment variable A = 0 at the same time. Since the value is not in the latest main memory, the value of A may still be 1 after the two threads execute the operation.

Java Volatile guarantees visibility

  • Java visibility guarantees go beyond the volatile variable itself, as follows:
    • If thread A writes to a volatile variable and thread B reads the same volatile variable, all variables before thread A writes to the volatile variable will also be visible after thread B reads the volatile variable.
    • If thread A reads a volatile variable, all variables visible to thread A at the time they are read are also fetched and refreshed from main memory.
public class myclass{ private int a; private int b; private volatile int c; public void update(int a,int b,int c){ this.a = a; this.b = b; this.c = c; }}Copy the code
  • When c is read, a and B are read from main memory again. When c is assigned, the values of a and B are flushed to main memory.

Variable instruction rearrangement

  • For performance reasons, the JVM and CPU can rearrange instructions in a program, as long as the semantics of the program remain the same.
int a = 1;
int b = 2;
a++;
b++;
Copy the code
  • Can be rearranged as
int a = 1;
a++;
int b = 2;
b++;
Copy the code
  • So looking back at the previous code, when instructions are reordered, it is possible that newly written values cannot be written to main memory. After c is written to main memory, a is reassigned by the thread, and volatile C has been written to main memory. As a result, the value in main memory of VOLATILE A is inconsistent with the value of its copy in the thread, causing data problems for calls made by other threads.
public void update(int a,int b,int c){
        this.b = b;
        this.c = c;
        this.a = a;
    }
Copy the code

Java Volatile solves the instruction rearrangement problem

  • Volatile provides happens-before to ensure that no instruction reordering occurs:
    • If reads and writes to other variables occur before volatile, reads and writes to other variables cannot be rearranged after volatile
    • If reading or writing of other variables occurs after volatile, the reading or writing of other variables cannot be rearranged before volatile

The performance of the volatile

  • Volatile variable reads and writes are accessed from main memory, and writing or reading from main memory has a higher performance cost than CPU caching. It is therefore better to use volatile to modify variables only when necessary.

Disadvantages of volatile – Atomicity is not guaranteed

  • If the actions of both threads are based on obtaining volatile variables, add them once they are acquired. Since this operation is not atomic (such as i++), it is possible for two threads to fetch variables from main memory and operate on their own CPU caches simultaneously. Thus, two threads have concurrency problems, again because volatile does not guarantee atomicity.

When might there be a problem

  • This is recommended when two threads simultaneously read and write variables, not atomic operationssynchronizedorjava.util.concurrent.

Afterword.

  • How many events through the ages? Leisurely. The Yangtze River is still rolling.