Java中读线程用独立synchronized块时写线程锁粗化是否仍被允许?
结论
写线程的锁粗化优化仍然完全符合JVM规范,是被明确允许的。
规范依据解释
1. JMM优化的核心约束原则
根据《Java语言规范(JLS)》第17章Java内存模型的规定:JVM可以对程序执行做任意优化,只要满足两个边界条件:
- 对于**正确同步(无数据竞争)**的程序,优化不能改变其执行结果;
- 对于存在数据竞争的程序,优化后产生的执行结果必须属于JMM允许的合法执行结果集合,不能引入原程序不可能出现的非法结果。
2. 本次场景的合法性分析
你给出的新场景中,所有对共享变量a、b的读写访问都被同一个this对象的synchronized块保护,属于正确同步的程序,不存在数据竞争。此时无论写线程是否做锁粗化,程序仅允许三种合法执行结果:
- r1=0、r2=0:读线程两次读都发生在写线程两次写之前
- r1=0、r2=1:读线程读b在写线程写b之前,读a在写线程写a之后
- r1=1、r2=1:读线程两次读都发生在写线程两次写之后
锁粗化不会新增或减少任何合法结果,完全符合规范要求: - 优化前写线程的两个独立
synchronized块,本身因为同属一个线程、按程序顺序执行,内部的a=1操作天然早于b=1操作存在happens-before关系; - 锁粗化只是合并了两次锁的获取/释放操作,扩大了锁的持有范围,既没有改变两个写操作的顺序,也没有破坏锁的互斥语义,不会影响程序的同步正确性。
3. 锁粗化本身的语义合法性
JVM规范从未要求同一个线程中相邻的、针对同一锁对象的synchronized块必须独立执行加解锁操作。锁粗化是JVM默认开启的标准优化,本质是消除不必要的加解锁开销,完全符合as-if-serial语义,不会对同步逻辑的正确性产生任何影响。
内容的提问来源于stack exchange,提问作者Eugene
相关产品推荐
相关产品推荐

