2016-08-17 101 views
1

假设我有一个名为MyCache的Java Bean,它有多个getter和setter。 我的应用程序中有一个MyCache实例。这是一个volatile字段myCacheMyCacheHolder。 当我需要刷新MyCache时,我创建了它的一个新副本(它需要时间),然后我只将参考myCache分配给这个新对象。同时刷新缓存

许多线程正在同时阅读MyCacheHolder#myCache。他们肯定会得到最新的参考,因为它是volatile。但我不确定他们是否得到完全初始化的对象。该对象通过setter进行初始化。阅读主题不能看到myCache的所有字段吗?如果是,那我该如何解决?

+3

如果你1)分配所有的值,然后2)将完全初始化的** MyCache分配给volatile字段,你没有问题。如果您在发布后以'_any_'的方式突变'MyCahce',那么您有一个问题。考虑到'MyCache'是在多个线程之间共享的,我会投入大量的时间和精力来使'MyCahce'成为**完全不可变的**类;那么就不存在陈旧状态的问题。 –

+0

是的,我完全是1)和2),但我仍然担心在分配给volatile变量之前通过setter设置到MyCache的某些值可能不会被其他线程看到。为了让其他线程可以看到某些“发生在......之前”的规则必须完成。 –

回答

1

制造领域myCachevolatile不足以使它线程安全的,则需要通过任何同步访问你的getter和setter或使MyCache不变(所有非静态字段使课堂MyCache线程安全也必须是final而且它们本身是不可变的)对我来说,最好的解决方案是使类不可变,因为一旦创建状态为实例的状态不能改变,它可以被任意数量的线程访问,而不需要同步对任何字段的访问。

0

如果缓存对象为真JavaBean(带一个参数的setter)和允许的缓存对象状态是通过调用多个setter来设置的,那么同步中的setter不起作用。

不变性与JavaBean规范有矛盾。

因此,如果您需要JavaBean - 在缓存外部对象中进行同步。

如果JavaBean不是强制性的 - 请使用不可变对象。