我正在使用以下字段:
private DateDao dateDao;
private volatile Map<String, Date> dates;
public Map<String, Date> getDates(){
return Collections.unmodifiableMap(dates);
}
public retireveDates(){
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")
return null
)
我认为您在问两个问题:
有了DAO代码,使用它的代码是否有可能使用它在此处得到的对象引用:
dates = dateDao.retrieveDates();
在dateDao.retrieveDates
引用的方法完成添加到该对象之前。例如,内存模型的语句重新排序语义是否允许该retrieveDates
方法在最后一个put
(等)完成之前返回引用?
一旦您的代码获得了dates
引用,就存在对代码中的非同步访问dates
以及通过的只读视图返回的问题getDates
。
您的领域是否volatile
与这些问题无关。使您的字段唯一起作用的volatile
是防止线程调用getDates
获取您的dates
字段的过时值。那是:
线程A线程B ---------- -------- 1.从dateDao.retrieveDates更新`date` 2.再次从“”更新“日期” 3. getDates返回只读 #1中的“ dates”视图
没有volatile
,上述情况是可能的(但无害)。使用volatile
,不是,线程B将看到dates
#2而不是#1的值。
但这与我认为您所问的任何一个问题都不相关。
不,您的retireveDates
(sic)中的代码无法看到填写该映射dateDao.retrieveDates
之前返回的对象引用dateDao.retrieveDates
。该内存模型允许重新排序语句,但是:
...编译器可以在不影响单独执行该线程的情况下,对每个线程中的指令重新排序
(我的重点是。)之前返回对代码的引用dateDao.retrieveDates
显然会孤立地影响线程的执行。
您显示的DAO代码永远不会修改它返回给您的地图,因为它不会保留它的副本,因此我们不必担心DAO。
在您的代码中,您没有显示任何可修改内容的内容dates
。如果您的代码没有修改的内容dates
,则无需进行同步,因为映射是不变的。您可能希望通过dates
在获取时(而不是在返回时)包装在只读视图中来确保这一点:
dates = Collection.unmodifiableMap(dateDao.retrieveDates());
如果您的代码确实dates
在未显示的地方进行了修改,那么是的,存在潜在的麻烦,因为Collections.unmodifiableMap
没有进行同步映射操作的操作。它只是创建一个只读视图。
如果要确保同步,则要包装dates
一个Collections.synchronizedMap
实例:
dates = Collections.synchronizedMap(dateDao.retrieveDates());
然后,您代码中对它的所有访问都将被同步,并且通过返回的只读视图对它的所有访问也将被同步,因为它们都通过了同步映射。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句