Когда можно использовать volatile, если он не обеспечивает атомарность чтения и записи как Atomic'и. Мне не понятно в чем разница между volatile и synchronized, если и то и другое обеспечивает синхронизацию между кэшами ядер процессора.
Ответ
Модификатор volatile гарантирует видимость операций с полем и сохранение их последовательности. Волатильную переменную можно, например, использовать как флаг завершения работы потока:
public class Main {
private static volatile boolean run = true;
public static void main(String[] args) throws Exception {
new Thread(() -> {
long x = 0;
while (run) {
System.out.println(++x);
try {
Thread.sleep(1000);
}
catch (InterruptedException exc) {}
}
}).start();
Scanner scanner = new Scanner(System.in);
while (run) {
String line = scanner.nextLine();
if ("exit".equals(line))
run = false;
}
}
}
Без модификатора volatile у вас нет гарантии, что поток выводящий значения переменной x когда-нибудь заметит, что главный поток изменил состояние переменной run
Синхронизация гарантирует видимость операций, сохранение их последовательности и атомарность.
public class Main {
private static int x = 0;
private static int y = 1000;
private static synchronized void transfer() {
++x;
--y;
}
public static void main(String[] args) throws Exception {
for (int a = 0; a < 10; a++) {
new Thread(() -> {
for (int b = 0; b < 100; b++) {
transfer();
}
}).start();
}
System.out.println(x);
System.out.println(y);
}
}
Без модификатора synchronized у вас нет гарантии, что значение переменной x будет увеличено на столько же, на сколько уменьшено значение переменной y, так как порядок и продолжительность выполнения потоков непредсказуемы.
Во втором примере volatile не поможет. В первом может помочь использование синхронизации, но тогда на каждой итерации один из потоков будет блокировать мьютекс, а второй потом будет останавливаться, пока мьютекс не будет освобождён. Это существенно медленнее проверки состояния волатильной переменной.
Комментариев нет:
Отправить комментарий