将对象引用存储到易失性字段中

Alupkers

我正在使用以下字段:

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

TJ人群

我认为您在问两个问题:

  1. 有了DAO代码,使用它的代码是否有可能使用它在此处得到的对象引用:

    dates = dateDao.retrieveDates();
    

    dateDao.retrieveDates引用方法完成添加到该对象之前。例如,内存模型的语句重新排序语义是否允许该retrieveDates方法在最后一个put(等)完成之前返回引用

  2. 一旦您的代码获得了dates引用,就存在对代码中的非同步访问dates以及通过的只读视图返回的问题getDates

您的领域是否volatile与这些问题无关。使您的字段唯一起作用的volatile是防止线程调用getDates获取您的dates字段的过时值那是:

线程A线程B
---------- --------
1.从dateDao.retrieveDates更新`date`
2.再次从“”更新“日期”
3. getDates返回只读
                                               #1中的“ dates”视图

没有volatile,上述情况是可能的(但无害)。使用volatile,不是,线程B将看到dates#2而不是#1的值。

但这与我认为您所问的任何一个问题都不相关。

问题1

不,您的retireveDates(sic)中的代码无法看到填写该映射dateDao.retrieveDates之前返回的对象引用dateDao.retrieveDates内存模型允许重新排序语句,但是:

...编译器可以在不影响单独执行该线程的情况下,对每个线程中的指令重新排序

(我的重点是。)之前返回对代码的引用dateDao.retrieveDates显然会孤立地影响线程的执行。

问题2

您显示的DAO代码永远不会修改它返回给您的地图,因为它不会保留它的副本,因此我们不必担心DAO。

您的代码中,您没有显示任何可修改内容的内容dates如果您的代码没有修改的内容dates,则无需进行同步,因为映射是不变的。您可能希望通过dates获取时(而不是在返回时)包装在只读视图中来确保这一点:

dates = Collection.unmodifiableMap(dateDao.retrieveDates());

如果您的代码确实dates在未显示的地方进行了修改,那么是的,存在潜在的麻烦,因为Collections.unmodifiableMap没有进行同步映射操作的操作。它只是创建一个只读视图。

如果要确保同步,则要包装dates一个Collections.synchronizedMap实例:

dates = Collections.synchronizedMap(dateDao.retrieveDates());

然后,您代码中对它的所有访问都将被同步,并且通过返回的只读视图对它的所有访问也将被同步,因为它们都通过了同步映射。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

通过易失性引用/指针访问声明的非易失性对象是否在所述访问中赋予了易失性规则?

来自分类Dev

引用类型的字段如何是非易失性的?

来自分类Dev

将对对象的引用存储在ArrayList中

来自分类Dev

易失性字典中的对象会继承易失性行为吗?

来自分类Dev

易失性字典中的对象会继承易失性行为吗?

来自分类Dev

如果直接从内存中读取易失性字段,那么从哪里读取非易失性字段?

来自分类Dev

将对象存储到数组中-Java

来自分类Dev

将对象数组存储到SQLite中?

来自分类Dev

C中的静态易失性与静态与易失性

来自分类Dev

允许对易失性对象进行优化

来自分类Dev

将对对象属性的引用存储在变量中

来自分类Dev

PHP将对象引用存储在数组中

来自分类Dev

将对对象属性的引用存储在变量中

来自分类Dev

Firemonkey TTreeView-将对象引用存储在TTreeViewItems,TValue中

来自分类Dev

引用创建的易失性表导致过程中不存在错误

来自分类Dev

在没有反射的情况下将对对象字段的引用传递并存储到另一个对象

来自分类Dev

将对象与字段中存储的类进行比较

来自分类Dev

了解C中的易失性变量

来自分类Dev

了解C中的易失性变量

来自分类Dev

在Java中无法将对象存储到列表中吗?

来自分类Dev

断电后易失性存储器的内容

来自分类Dev

对非易失性字段的同步访问是否安全?

来自分类Dev

Java“发生之前”与易失性字段有关

来自分类Dev

非易失性字段+来自另一个线程的第一个对象访问(java)

来自分类Dev

.NET中可变的新鲜度保证(易失性与易失性读取)

来自分类Dev

C#中的对象实例化之间的区别:将对象存储在引用中与直接调用方法

来自分类Dev

将对象存储在localStorage中

来自分类Dev

将对象存储到列表中并为其命名存储在 R 中的字符向量中

来自分类Dev

如果在加载引用和对其调用函数之间的线程之间更改了易失性引用,那么是否可以对旧对象进行垃圾回收?

Related 相关文章

  1. 1

    通过易失性引用/指针访问声明的非易失性对象是否在所述访问中赋予了易失性规则?

  2. 2

    引用类型的字段如何是非易失性的?

  3. 3

    将对对象的引用存储在ArrayList中

  4. 4

    易失性字典中的对象会继承易失性行为吗?

  5. 5

    易失性字典中的对象会继承易失性行为吗?

  6. 6

    如果直接从内存中读取易失性字段,那么从哪里读取非易失性字段?

  7. 7

    将对象存储到数组中-Java

  8. 8

    将对象数组存储到SQLite中?

  9. 9

    C中的静态易失性与静态与易失性

  10. 10

    允许对易失性对象进行优化

  11. 11

    将对对象属性的引用存储在变量中

  12. 12

    PHP将对象引用存储在数组中

  13. 13

    将对对象属性的引用存储在变量中

  14. 14

    Firemonkey TTreeView-将对象引用存储在TTreeViewItems,TValue中

  15. 15

    引用创建的易失性表导致过程中不存在错误

  16. 16

    在没有反射的情况下将对对象字段的引用传递并存储到另一个对象

  17. 17

    将对象与字段中存储的类进行比较

  18. 18

    了解C中的易失性变量

  19. 19

    了解C中的易失性变量

  20. 20

    在Java中无法将对象存储到列表中吗?

  21. 21

    断电后易失性存储器的内容

  22. 22

    对非易失性字段的同步访问是否安全?

  23. 23

    Java“发生之前”与易失性字段有关

  24. 24

    非易失性字段+来自另一个线程的第一个对象访问(java)

  25. 25

    .NET中可变的新鲜度保证(易失性与易失性读取)

  26. 26

    C#中的对象实例化之间的区别:将对象存储在引用中与直接调用方法

  27. 27

    将对象存储在localStorage中

  28. 28

    将对象存储到列表中并为其命名存储在 R 中的字符向量中

  29. 29

    如果在加载引用和对其调用函数之间的线程之间更改了易失性引用,那么是否可以对旧对象进行垃圾回收?

热门标签

归档