Java内存模型中的可见性指线程修改共享变量后其他线程能否及时看到新值,根本原因在于JMM将变量存于主内存而线程操作工作内存副本,且同步无强制时机;volatile通过强制读写主内存解决可见性,但不保证原子性;synchronized等锁机制也通过happens-before规则保障可见性。
Java内存模型(JMM)中的可见性,指的是:当一个线程修改了共享变量的值,其他线程能否及时看到这个新值。
根本原因在于JMM对内存的抽象划分:
这就导致:线程A把flag设为true,但只更新了自己的副本
;线程B还在用自己缓存的老值false,死循环卡住。
给变量加上volatile修饰后,它就具备两个关键语义:
它不加锁、不阻塞,适合“一写多读”且不需要原子性的场景,比如状态标志位(running、shutdown等)。
synchronized、ReentrantLock等同步机制,不只是为了互斥,也天然提供可见性保障:
这是由JMM的happens-before规则保证的:解锁操作happens-before后续的加锁操作。所以用锁保护的共享变量,修改对其他线程必然可见。
volatile能保可见,但不保原子性:
count++这种复合操作(读-改-写),即使count是volatile,多个线程仍可能互相覆盖结果基本上就这些。可见性看似简单,但容易忽略底层缓存和副本机制,写并发代码时务必留心。