Важливий момент про volatile:
- Синхронізація в Java можна за допомогою Java ключових слів
synchronizedі volatileі замки.
- У Java ми не можемо мати
synchronizedзмінну. Використання synchronizedключового слова зі змінною є незаконним і призведе до помилки компіляції. Замість використання synchronizedзмінної в Java, ви можете використовувати volatileзмінну java , яка доручить потокам JVM зчитувати значення volatileзмінної з основної пам'яті та не кешувати її локально.
- Якщо змінна не поділяється між декількома потоками, тоді не потрібно використовувати
volatileключове слово.
джерело
Приклад використання volatile:
public class Singleton {
private static volatile Singleton _instance; // volatile variable
public static Singleton getInstance() {
if (_instance == null) {
synchronized (Singleton.class) {
if (_instance == null)
_instance = new Singleton();
}
}
return _instance;
}
}
Ми створюємо екземпляр ліниво під час першого запиту.
Якщо ми не зробимо _instanceзмінну, volatileто Нитка, яка створює екземпляр Singleton, не зможе передавати інший потік. Отже, якщо Thread A створює екземпляр Singleton і відразу після створення CPU псується тощо, всі інші потоки не зможуть побачити значення _instanceяк недійсне, і вони вважатимуть, що це все-таки присвоєно нулю.
Чому це відбувається? Оскільки потоки читачів не роблять жодного блокування і поки потік запису не вийде із синхронізованого блоку, пам'ять не буде синхронізована, і значення _instanceне буде оновлено в основній пам'яті. З ключовим словом Volatile на Java цим керує сама Java, і такі оновлення будуть видимі в усіх потоках читачів.
Висновок : volatileключове слово також використовується для передачі вмісту пам'яті між потоками.
Приклад використання без летких:
public class Singleton{
private static Singleton _instance; //without volatile variable
public static Singleton getInstance(){
if(_instance == null){
synchronized(Singleton.class){
if(_instance == null) _instance = new Singleton();
}
}
return _instance;
}
Код, наведений вище, не є безпечним для потоків. Хоча він ще раз перевіряє значення екземпляра в синхронізованому блоці (з міркувань продуктивності), компілятор JIT може переставити байт-код таким чином, що посилання на екземпляр встановлюється до того, як конструктор закінчить його виконання. Це означає, що метод getInstance () повертає об'єкт, який, можливо, не був ініціалізований повністю. Щоб зробити нитку коду безпечною, ключове слово мінливе може використовуватися з Java 5 для змінної екземпляра. Змінні, позначені як мінливі, стають видимими лише для інших потоків після того, як конструктор об'єкта закінчив його виконання повністю.
Джерело

volatileвикористання на Java :
Ітератори виходу з ладу, як правило, реалізуються за допомогою volatileлічильника на об'єкті списку.
- Коли список оновлюється, лічильник збільшується.
- Коли
Iteratorстворюється, поточне значення лічильника вбудовується в Iteratorоб'єкт.
- Коли
Iteratorвиконується операція, метод порівнює два значення лічильника і кидає a, ConcurrentModificationExceptionякщо вони різні.
Запровадження ітераторів безвідмовної роботи, як правило, мало важить. Вони, як правило, покладаються на властивості структур даних конкретної реалізації списку. Загальної закономірності немає.
volatileцієї функції з новою моделлю пам'яті Java, визначеною в JSR 133: що, коли нитка читаєvolatileзмінну, вона бачить не тільки значення, останнє, записане до неї іншим потоком, а й усі інші записи в інші змінні, які були помітні в тій іншій нитці під часvolatileнаписання. Дивіться цю відповідь та цю посилання .