Ошибка при работе с volatile
Как мне известно volatile обеспечивает атомарность. И немного не могу понять почему count выдает разные значения. Знаю, что инкремент является не атомарным и поэтому написал так.
public class Main{
public static volatile int count = 0;
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10000; i++) {
count = count - 1;
}
}
});
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
for (int j = 0; j < 10000; j++) {
count = count + 1;
}
}
});
thread.start();
thread1.start();
thread.join();
thread1.join();
System.out.println(count);
}
}
Ответы (1 шт):
Автор решения: Komdosh
→ Ссылка
volatile не обеспечивает атомарность. Данное ключевое слово заявляет, что каждая отдельная операция записи или чтения будет видна другим потокам. volatile по большей части помогает компилятору понять, что с этой переменной надо работать аккуратнее, например предотвращать reordering операций.
Инкремент count++ выполняет 3 отдельные операции чтения, сложения, записи:
count = count + 1
Поэтому допустима ситуация (T1 и T2 - потоки):
- T1: Чтение count (count == 0)
- T2: Чтение count (count == 0)
- T1: Запись count + 1 (count == 1)
- T2: Запись count + 1 (count == 1) -- T2 в контексте хранит, что count == 0, хотя T1 уже произвёл запись
- T2: Чтение count (count == 1)
Для атомарности используйте AtomicInteger.