Java多属性同步操作:synchronized锁是否需配合volatile?
问题解答
结论:第一段代码完全正确,不需要给属性添加volatile关键字
1. synchronized块的可见性保证
Java的synchronized关键字不仅保证操作的互斥性,还提供完整的内存可见性语义:
- 线程进入
synchronized(lockObject)块时,会清空当前线程工作内存中所有共享变量的副本,必须从主内存重新读取最新值; - 线程退出
synchronized块时,会把当前线程工作内存中所有共享变量的修改强制刷新到主内存; - 更关键的是happens-before规则:线程A退出某个锁的同步块,必然"先于"线程B进入同一锁的同步块执行。这意味着A在块内对
a、b、y的所有修改,对后续获取同一锁的线程来说都是完全可见的。
2. 锁对象是final无状态的不影响效果
锁对象的作用只是作为一个同步标识,用来绑定所有需要同步的操作,和它自身有没有状态毫无关系。只要所有访问a、b、y的线程,都通过同一个lockObject的synchronized块来读写,就能保证这些属性的操作是线程安全的(原子性+可见性)。你担心的"锁无状态final对象无意义"是误解,锁的核心是同一标识下的同步互斥与内存屏障,和锁对象本身的状态无关。
3. 第二段代码的volatile是多余的
volatile的作用是让变量的读写直接操作主内存,避免线程工作内存的缓存。但当这些属性的所有读写都被synchronized块包裹时,synchronized已经提供了比volatile更强的内存可见性保证(还附带原子性),此时添加volatile属于重复操作,不会带来任何额外收益,反而没必要。
唯一需要注意的是:如果存在线程在synchronized块外直接读取或修改a、b、y,那确实需要额外的可见性保证,但根据你给出的代码结构,假设所有操作都在同步块内,那完全不需要volatile。
内容的提问来源于stack exchange,提问作者Fexl
相关产品推荐
相关产品推荐

