“This article has participated in the good article call order activity, click to see: back end, big front end double track submission, 20,000 yuan prize pool for you to challenge!”

Volatile is introduced

The Java language provides a lightweight synchronization mechanism, volatile variables, also known as lightweight locking, to ensure that updates to variables are notified to other threads.

  1. Volatile guarantees visibility
  2. Volatile does not guarantee atomicity
  3. Volatile disallows order reordering

When we start with volatile visibility, we first need to understand the JMM

JMM

The JMM (Java Memory Model) itself is an abstract concept rather than a real one. The JMM description is a set of rules or specifications that define how variables (instance fields, static fields, elements that make up array objects) in a program are accessed.

Prior to JDK1.2, JMM implementations always read variables from main memory (that is, shared memory) without any special care. Under the current Java memory model, threads can store variables in local memory (such as machine registers) rather than directly reading or writing to main memory. This can cause one thread to modify the value of a variable in main memory, while another thread continues to use its copy of the variable value in the register, resulting in data inconsistency.

JMM regulations on synchronization:

1. Before unlocking the thread, the shared variable value must be updated to main memory.

2. Before locking, the thread must read the latest value in the main memory to its own working memory.

3. Lock and unlock the same lock.

  • The JVM runs programs through threads. When each thread is created, the JVM creates a working memory for it. Working memory is a thread-private area, while the JMM specifies that all variables are stored in main memory.

  • Main memory is a thread shared memory area that can be accessed by all threads, but thread operations on variable pairs must take place in the working memory.

  • First variable from main memory to copy their own memory space, and then to operating variables, operation to complete before you write variables back to main memory, no direct operating variables in main memory, working memory storage in various threads of variables in the main memory copy copy, so don’t have access to each other between different threads of working memory, Communication between threads must be done through main memory.

To summarize, threads operating on data in main memory go through the following procedure

  1. Copies copies from main memory to working memory
  2. Working on the copy
  3. Write the variable back to memory after the operation is complete

If thread A writes the data to main memory and changes it to 99, but thread B does not know that thread A has changed the tickets in main memory since thread B copied the original tickets when tickets=100, then thread B needs A mechanism to notify other threads in time after the change is written. This mechanism is JMM visibility

Access process diagram

The code proves that volatile guarantees visibility

public class Solution {

    public static void main(String[] args) {
        MyTask myTask = new MyTask();
        new Thread(() -> myTask.sell(), "Thread A").start();
        while (myTask.tickets == 100) {

        }
        System.out.println("main~~~~~~"); }}class MyTask {
    volatile int tickets = 100;

    public void sell(a) {
        System.out.println(Thread.currentThread().getName() + "\t start~~~");
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        tickets--;
        System.out.println(Thread.currentThread().getName() + "\t update ok and tickets ="+ tickets); }}Copy the code

1. Let’s look at the situation without volatile

int tickets = 100;
Copy the code

You can see that the main thread is stuck in the while loop without knowing that tickets have been changed to 99

2. If volatile is used

volatile int tickets = 100;
Copy the code