Java并发多线程安全发布实例
Java并发在实践中表示,通过将一个有效的不可变对象(例如,一个您构建的、永远不会再更改的日期对象)粘贴到一个同步集合中,您可以安全地发布它,如下所示(摘自本书第53页):
public Map<String, Date> lastLogin =
Collections.synchronizedMap(new HashMap<String, Date>())
我知道,一旦放入这个同步映射中,放入这个映射中的任何日期对象都是可见的(至少在其初始但完全构造的状态下),但只有当其他线程能够获得对这个映射对象的引用时
由于引用字段lastLogin没有保证可见性的字段属性(final、volatile、guarded或由静态初始值设定项初始化),我认为映射本身可能不会以完全构造的状态显示给其他线程,因此本末倒置。还是我错过了什么
# 1 楼答案
您的怀疑有一半是对的,因为
lastLogin
的值不能保证对其他线程可见。因为lastLogin
不是volatile
或final
,所以另一个线程可以将其读取为null
但是,您不必担心其他线程会看到地图的不完整版本
Collections.synchronizedMap(...)
返回带有final
字段的a private class实例JLS section 17.5说:SynchronizedMap
遵循这些规则,因此另一个读取lastLogin
的线程将要么读取null
或者对完全构造的映射的引用,而不是对不完整或不安全的映射版本的引用