2016-08-17 74 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不是強制性的 - 請使用不可變對象。