可见性volatile
About 1 min
可见性
public class VolatileTest {
private static boolean running = true;
public static void main(String[] args) throws InterruptedException {
new Thread(() -> {
System.out.println("Thread start, time: " + LocalDateTime.now());
while (running) {
}
System.out.println("Thread end, time: " + LocalDateTime.now());
}).start();
TimeUnit.SECONDS.sleep(3);
running = false;
}
}
输出结果:
Thread start, time: 2023-09-04T11:01:56.216820
一直都没能结束,如果在第二行加上volatile
修饰符。那么输出结果如下:
Thread start, time: 2023-09-04T11:03:50.573060
Thread end, time: 2023-09-04T11:03:53.559628
非原子性
public class VolatileTest {
volatile int count = 0;
void increment() {
for (int i = 0; i < 10000; i++) {
count++;
}
}
public static void main(String[] args) throws InterruptedException {
var volatileTest = new VolatileTest();
var threads = new ArrayList<Thread>();
for (int i = 0; i < 10; i++) {
threads.add(new Thread(volatileTest::increment));
}
for (Thread thread : threads) thread.start();
for (Thread thread : threads) thread.join();
System.out.println(volatileTest.count);
}
}
输出的结果不确定,但是一般会小于10000
:
38596
解决办法,可以使用提供CAS功能的AtomicInteger
,它既满足原子性要求,还同时拥有可见性。
AtomicInteger count = new AtomicInteger();
void increment() {
for (int i = 0; i < 10000; i++) {
count.incrementAndGet();
}
}
禁止指令重排序
内存读写屏障
指令重排序
FAQ
Lamda表达式里面的异常不能throw?
Long或者Doudble的读写是原子性的吗?
long和double的读写不是原子性的,但是加了volatile就是原子性的。