Volatile обеспечивает чтение и запись в память программы в обход кеша. Мы должны использовать volatile, когда есть общий ресурс, такой как целочисленная переменная. Итак, я провел небольшой эксперимент. Сначала у меня были следующие классы:
public class Main3 {
static int j = 0;
public static void main(String[] args) throws InterruptedException {
new Thread1().start();
new Thread2().start();
}
static int i = 0;
static class Thread1 extends Thread{
@Override
public void run() {
while(i<5){
System.out.println("thread1 i = "+i);
i++;
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
static class Thread2 extends Thread{
@Override
public void run() {
int val = i;
while(val<5){
if(val!=i) {
System.out.println("thread2 i = " + i);
val = i;
}
}
}
}
}
В первом потоке переменная меняет свое значение. Второй поток отслеживает изменение и отображает текст на консоли, если это произошло
Переменная i является общим ресурсом. И без volatile программа печатает то, что ожидалось, и не может:
thread1 i = 0
thread1 i = 1
thread1 i = 2
thread1 i = 3
thread1 i = 4
Но, если я сделаю это (добавим сон в класс Thread2):
static class Thread2 extends Thread{
@Override
public void run() {
int val = i;
while(val<5){
if(val!=i) {
System.out.println("thread2 i = " + i);
val = i;
}
try {
sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
, программа напечатает это и успешно закончено:
thread1 i = 0
thread2 i = 1
thread1 i = 1
thread2 i = 2
thread1 i = 2
thread2 i = 3
thread1 i = 3
thread2 i = 4
thread1 i = 4
thread2 i = 5
Итак, если потоки кэшируют значения, то почему исчезает кэширование сна с появлением сна?