簡體   English   中英

Java 並發與集合

[英]Java Concurrency with Sets

對於下面的函數,我試圖返回一個新的 Set mHashSet ,它是另一個集合iGraphicSectors的副本:

public Set<String> getGraphics() {
    synchronized (iGraphicSectors) {  // class variable of type Set<String>
        LinkedHashSet<String> mHashSet = new LinkedHashSet<String>();
        synchronized (mHashSet) {
            mHashSet.addAll(iGraphicSectors);
        }
        return mHashSet;
    }
}

然而第 5 行mHashSet.addAll(iGraphicSectors); 正在拋出ConcurrentModificationException (我不確定這怎么可能)。 有沒有辦法以線程安全的方式完成上述任務?

您需要做的是對iGraphicSectors使用線程安全的Set ,因為您顯然是同時讀取和修改它的,最簡單的方法是使用裝飾器Collections.synchronizedSet(Set<T> s)來制作當前的Set線程安全,由於裝飾器,任何讀取和寫入訪問都將使用synchronized塊自動保護,但是您仍然需要使用synchronized塊顯式保護它的迭代。

以下是如何創建它的示例:

Set<String> iGraphicSectors = Collections.synchronizedSet(new HashSet<String>());

以下是您的代碼的外觀:

public Set<String> getGraphics() {
    // Still needed as the constructor of LinkedHashSet will iterate
    // over iGraphicSectors 
    synchronized (iGraphicSectors) {  
        return new LinkedHashSet<String>(iGraphicSectors);
    }
}

從您的最新評論中,聽起來您只是想讓Set不可變 - 您可以在不使用任何同步原語的情況下做到這一點:

return Collections.unmodifiableSet(iGraphicSectors);

在此函數的末尾(請參閱文檔)。

作為旁注,很明顯您不想使用同步,因為Set是在函數內部構造的。 它對程序中執行的其他線程沒有任何可見性。 如果要進行任何同步,則不在此方法中

真正的問題是,這個方法返回的Set會改變嗎? 如果是這樣,你可以從這個函數返回一個同步的Set

return Collections.synchronizedSet(...)

在此函數的末尾(再次參見文檔)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM