2013-11-04 48 views
1

。 我在練習冊中遵循Java Concurrency。 當涉及到安全地發佈,特別是與最終的,我很清楚,首先參考將是所有其他線程可見,其次發佈的對象的狀態是任何其他線程可見,但這裏的問題是,如果狀態引用的數組元素保證在它發佈的狀態下可見? (當然,只要沒有人修改這些數據對象)。Java只是爲了確保安全地發佈最終的

例子:

@Mutable 
public class NotThreadsafeDataObject { 

    private String message; 

    public NotThreadsafeDataObject (String message) { 
     this.message = message; 
    } 

    public String getMessage() { 
     return message; 
    } 

    public void setMessage(String message) { 
     this.message = message; 
    } 

} 

現在讓我們發佈安全可變對象的數組:

public class Publish { 

    public final NotThreadsafeDataObject[] publish; 

    public Publish() { 
     publish = new NotThreadsafeDataObject[] { new NotThreadsafeDataObject("one"), new NotThreadsafeDataObject("two")}; 

    } 

} 
+0

據我所知,最後表明(對於對象)引用不會改變。但是,該對象的內部狀態可能仍然會發生變化,並且線程仍然可以使用它們自己的內部緩存。 volatile關鍵字阻止線程保留自己的緩存 –

+0

發佈之後,引用的對象及其引用的對象不會更改...讓我們按慣例說。我想知道使用final字段進行安全發佈後數組內引用的可變對象的可見性。 – user2050516

回答

0

如果我們在提交的「Java併發編程實踐」方面講那麼你的陣列是一個「有效不可變的「對象。對於這樣的對象來說,安全的發佈對於不破壞內部狀態而言總是必要的。所以你的代碼是可以的,因爲你正在使用安全的發佈。更具體地說,「最終」關鍵字內存語義保證訪問最終字段的線程將看到在寫入字段之前發生的所有事情(「發生之前」已建立)。

0

我很確定你仍然可以修改你的數組中的單個可變對象的值。即

publish[0].setMessaage("Hello"); 

會工作得很好。而且我相信你可以從你的陣列中刪除對象。它是無法更改的數組引用,因爲它被聲明爲final。如果你想擁有完全不可變集合我會被聲明爲final和列表工作,然後創建一個新的單獨的列表,填充,然後使用方法public static List unmodifiableList(List list)它assig到您的最終名單:

ublic class Publish { 

    public static final List<NotThreadsafeDataObject> publish; 

    static { 
     init(); 
    } 

    private static void synchronized init() { 
     List<NotThreadsafeDataObject> list = new ArrayList<>(); 
     list.add(new NotThreadsafeDataObject("one"); 
     list.add(new NotThreadsafeDataObject("two"); 
     publish = Collections.unmodifiableList(list); 
    } 
} 

這使得防彈的完全不變的名單,既不參考它也不改變其內容。