Java中未添加println语句时锁无法正常撤销的问题咨询
问题成因
该问题本质是Java内存模型下的共享变量可见性问题:
- Java内存模型规定,每个线程拥有独立的工作内存,会将主内存中的共享变量(此处为
server.lock)缓存到本地工作内存。默认无同步操作时,线程不会主动从主内存刷新共享变量的值,只会读取本地缓存的副本,因此其他线程修改了主内存中server.lock的值后,当前线程感知不到变更,while循环就会一直卡死。 - 加入
println语句后运行正常,是因为println底层实现包含synchronized同步逻辑:进入同步块时线程会清空工作内存的共享变量缓存,强制从主内存读取最新值,退出同步块时会把本地修改刷回主内存。因此每次执行println都会刷新server.lock的缓存,线程就能感知到变量变更,循环可以正常退出。
解决方案
方案1:给共享变量加volatile修饰
将server.lock的定义修改为volatile int lock即可。volatile关键字会禁止线程对该变量的本地缓存,每次读取强制从主内存拉取,每次修改立刻刷回主内存,直接解决可见性问题,是该场景下成本最低的方案。
方案2:使用Java标准并发工具实现互斥
不要自行手写锁变量控制互斥,直接用JDK提供的java.util.concurrent.locks.ReentrantLock等标准锁工具,标准实现已经完整处理了原子性、可见性、可重入等多线程场景的边界问题,稳定性远高于自行实现的锁逻辑。
方案3:给变量读取操作加同步控制
在循环中读取server.lock的代码外层包裹synchronized同步块,也能触发主内存刷新,不过该方案性能比volatile差,不推荐优先使用。
内容的提问来源于stack exchange,提问作者Pm P
相关产品推荐
相关产品推荐

