Volatile
1. Ensure visibility
package com.chao.cvolatile;
import java.util.concurrent.TimeUnit;
public class JMMDemo {
// If not volatile, the program will loop forever!
// Volatile ensures visibility
private volatile static int num = 0;
public static void main(String[] args) { // main thread main
new Thread(()->{Thread 1 is unaware of the main memory changes
while(num==0){
}
}).start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
num = 1; System.out.println(num); }}Copy the code
2,Atomicity is not guaranteed
Atomicity: ACID indivisible
Thread A cannot be interrupted or split while performing tasks. You either succeed at the same time or you fail at the same time.
package com.chao.tvolatile;
// Volatile does not guarantee atomicity
public class VDemo02 {
// Volatile does not guarantee atomicity
private volatile static int num = 0;
public static void add(a){
num++;
}
public static void main(String[] args) {
// In theory the num result should be 20,000
for (int i = 1; i <=20; i++) {
new Thread(()->{
for (int j = 0; j <1000 ; j++) {
add();
}
}).start();
}
while(Thread.activeCount()>2) {//main gc
Thread.yield();
}
System.out.println(Thread.currentThread().getName() + ""+ num); }}Copy the code
How can atomicity be guaranteed without locking and synchronized
Use atomic classes to solve atomicity problems
package com.chao.tvolatile;
import java.util.concurrent.atomic.AtomicInteger;
// Volatile does not guarantee atomicity
public class VDemo02 {
// Volatile does not guarantee atomicity
// Integer of the atomic class
private volatile static AtomicInteger num = new AtomicInteger();
public static void add(a){
//num++; // Not an atomic operation
num.getAndIncrement(); //AtomicInteger + 1 method, the concurrency primitive of CAS CPU
}
public static void main(String[] args) {
// In theory the num result should be 20,000
for (int i = 1; i <=20; i++) {
new Thread(()->{
for (int j = 0; j <1000 ; j++) {
add();
}
}).start();
}
while(Thread.activeCount()>2) {//main gc
Thread.yield();
}
System.out.println(Thread.currentThread().getName() + ""+ num); }}Copy the code
The bottom layers of these classes hook directly to the operating system! Modify values in memory! The Unsafe class is a very special existence!
Instruction rearrangement
What is instruction reordering: The computer does not execute the program you write.
Source code –> compiler optimizations –> instruction parallelism may also be rearranged –> memory systems –> execution
When the processor rearranges instructions, it considers the dependency between data.
int x = 1; / / 1
int y = 2; / / 2
x = x + 5; / / 3
y = x * x; / / 4What we expect:1234But maybe when you do it, it becomes2134 1324Could it be4123!Copy the code
Possible results: The default values of a, B, x, and y are 0
Thread A | Thread B |
---|---|
x=a | y=b |
b=1 | a=2 |
Normal result: x = 0; y = 0; But it may be due to reordering
Thread A | Thread B |
---|---|
b=1 | a=2 |
x=a | y=b |
Weird result caused by instruction rearrangement: x=2; y=1;
Non-computer major
Volatile prevents instruction reordering:
Memory barrier, CPU instructions. Function:
1, ensure the execution order of specific operations!
2. Memory visibility is guaranteed for certain variables (visibility is achieved using volatile)
Volatile can maintain visibility. Atomicity is not guaranteed. Thanks to the memory barrier, instruction reordering is guaranteed to be avoided!