【发布时间】:2016-04-28 21:00:37
【问题描述】:
我正在使用以下字段:
private DateDao dateDao;
private volatile Map<String, Date> dates;
public Map<String, Date> getDates() {
return Collections.unmodifiableMap(dates);
}
public retrieveDates() {
dates = dateDao.retrieveDates();
}
在哪里
public interface DateDao {
//Currently returns HashMap instance
public Map<String, Date> retrieveDates();
}
以这种方式发布日期地图是否安全?我的意思是,易失性字段意味着对字段的引用不会被缓存在 CPU 寄存器中,并且不会在任何时候被访问时从内存中读取。
因此,我们不妨读取state of the map 的陈旧值,因为HashMap 不进行任何同步。
这样做安全吗?
UPD:例如假设DAo方法以如下方式实现:
public Map<String, Date> retrieveDates() {
Map<String, Date> retVal = new HashMap<>();
retVal.put("SomeString", new Date());
//ad so forth...
return retVal;
}
可以看出,Dao 方法不做任何同步,HashMap 和Date 都是可变的,不是线程安全的。现在,我们已经创建并发布了它们,如上所示。是否保证从另一个线程对dates 的任何后续读取不仅会观察到对Map 对象的正确引用,还会观察到它的“新鲜”状态。
我不确定线程是否不能观察到一些陈旧的值(例如 dates.get("SomeString") 返回 null)
【问题讨论】:
-
“安全”在什么意义上?对
getDates的调用总是会看到来自retrieveDates的最新分配的地图?还是……? -
@T.J.Crowder 调用 getDates 总是会看到最近分配的地图你为什么这么认为?没有同步
JIT允许执行任何与内存模型兼容的优化。在 Dao 中创建和填充 Map 不涉及任何同步,而且 HashMap 不是线程安全的。我有点担心。 -
@T.J.Crowder 我的问题实际上是。仅存储对不会被修改为
volatile字段的对象的引用以安全地发布它真的就足够了吗?即使在发布之前对对象进行创建和其他一些操作也不需要同步。 -
我在问你在问什么,而不是在断言什么。要澄清您的问题,请使用问题上的“编辑”链接,而不是 cmets。
-
只是一种英语 仅供参考:“你能看一下吗?”是要求某人看某物的请求。 “不能你看看吗?”是他们没有抱怨。 :-)(疯狂的语言,嗯?)我会看一下,但我可能没有足够的知识来回答(只是为了确定需要更多细节)。
标签: java multithreading volatile