laitimes

Java Concurrency! What interview points should Volatile keywords have?

Preface: Although the number of concurrent readings is not very large in the past few days, I still want to mention it. Java Concurrency Basics + Design Patterns are really important! The foundation is solid, and the reading of the framework and source code can be more convenient, and when we have the ability to read the source code, it can also help us improve efficiency. (Of course, for some big guys, learning different thinking is not a bad thing, and I hope that big guys can correct the mistakes in my article.) Sincere! )。

I'll repeat the Volatile keyword today.

One of the happens-before rules:

Writes to a volatile field happen-before any subsequent reads of the volatile field. (Collection article by specific explanation ha)

How does JMM disable reordering?

Memory Barriers / Fences

To implement the memory semantics of volatile, the compiler, when generating bytecode, inserts memory barriers in the sequence of instructions to prevent specific types of processor reordering

This sentence is a bit abstract, try to imagine that the memory barrier is a high wall, if there is this barrier between the two variables, then they cannot swap positions (reorder), variables have read (Load) and write (Store), the operation has before and after, JMM divides the memory barrier insertion strategy into 4 types:

  1. Insert a StoreStore barrier in front of each volatile write
  2. Insert a StoreLoad barrier after each volatile write operation
  3. Insert a LoadLoad barrier after each volatile read operation
  4. Insert a LoadStore barrier after each volatile read operation

1 and 2 are described graphically and the corresponding table rules look like this:

Java Concurrency! What interview points should Volatile keywords have?

3 and 4 Graphical descriptions and corresponding table rules look like this:

Java Concurrency! What interview points should Volatile keywords have?

The reading and writing of a program is usually not as simple as the above two cases, how can these barriers be used together? In fact, it is not difficult at all, we just need to bring these instructions into the table at the beginning of the article, and then stitch the instructions according to the program order

public class VolatileBarrierExample {
 private int a;
 private volatile int v1 = 1;
 private volatile int v2 = 2;
void readAndWrite(){
 int i = v1; //第⼀个volatile读
 int j = v2; //第⼆个volatile读
 a = i + j; //普通写
 v1 = i + 1; //第⼀个volatile写
 v2 = j * 2; //第⼆个volatile写
 }
}           

Bringing the barrier directive into the program looks like this:

Java Concurrency! What interview points should Volatile keywords have?

Let's look at the above diagram from several angles:

  • Color is the "safest" solution that brings the barrier instructions into the program to be generated
  • Obviously, there are many barriers that are repetitive and redundant, and the barrier pointed to by the dotted box on the right is the barrier that can be "optimized" to remove

Memory semantics for volatile write-read

Suppose thread A executes the writer method first, followed by thread B executing the reader method

public class ReorderExample {
 private int x = 0;
 private int y = 1;
 private volatile boolean flag = false;
 public void writer(){
 x = 42; //1
 y = 50; //2
 flag = true; //3
 }
 public void reader(){
 if (flag){ //4
 System.out.println("x:" + x); //5
 System.out.println("y:" + y); //6
 }
 }
}           

When thread A executes the writer method:

Java Concurrency! What interview points should Volatile keywords have?

Thread A writes the variables changed in local memory back to main memory.

Memory semantics for volatile reads:

When reading a volatile variable, JMM invalidates the thread's corresponding local memory. The thread will next read the shared variable from main memory

So when thread B executes the reader method, the graph structure looks like this

Java Concurrency! What interview points should Volatile keywords have?

Thread B local memory variable is invalid, read the variable from main memory to local memory, and get the result of thread A's change, which is how volatile ensures visibility

If you have read the previous article, it is not difficult for you to understand the above two pictures, combined to say:

  1. Thread A writes a volatile variable, essentially thread A sends a message (its modifications to the shared variable) to one of the threads that will read the volatile variable next
  2. Thread B reads a volatile variable, essentially thread B receives a message from a previous thread that modified the shared variable before the volatile variable was written.
  3. Thread A writes a volatile variable, and then thread B reads the volatile variable, essentially by thread A sending a message to thread B through main memory.