2010-10-11 60 views
1

我在我的代碼中有一個靜態的HashSet對象引用,它必須在給定的方法正在運行之前不允許所有寫入請求(它僅將哈希集用於讀取目的)。我已閱讀線程基礎知識,但尚不清楚如何繼續這樣做。在Java中鎖定哈希集合

任何人都可以幫我嗎?

+0

什麼意思是不允許的?塊?拋出異常? – 2010-10-11 17:21:39

+0

拼寫檢查:我想不是「在給定方法運行之前不允許所有寫請求」應該是「在給定方法運行時不允許所有寫請求」? – 2010-10-11 17:29:17

+1

此外,使用示例代碼發佈您的問題會很有幫助 - 使您的問題更清晰易懂,並且更易於回答。 – 2010-10-11 17:30:10

回答

9

您提到您已閱讀線程基礎知識,因此我假設您有一個多線程應用程序,您有多個閱讀器和/或作者。您可以使用讀寫鎖來限制對該集合的訪問。當給定的方法執行時,它鎖定讀取鎖定,允許其他人讀取,但不寫入。只要您使用下面的putInSet方法(或類似方法)編寫代碼,就可以要求寫入鎖寫入。然後在讀鎖被保持時,該組不能寫入。

private final Set<Object> mySet = new HashSet<Object>(); 
private final ReadWriteLock lock = new ReentrantReadWriteLock(); 
public void methodThatRunsAndAllowsReadOnly() { 
    lock.readLock().lock(); 
    try { 
     // method body here 
    } 
    finally { 
     lock.readLock().unlock(); 
    } 
} 

public void putInSet(Object o) { 
    lock.writeLock().lock(); 
    try { 
     mySet.add(o); 
    } 
    finally { 
     lock.writeLock().unlock(); 
    } 
} 
+0

+1使用讀寫鎖。 – 2010-10-11 22:28:02

+0

我正在查看ReentrantReadWriteLock的javadocs,它說,如果不首先釋放讀取鎖定,則無法升級到寫入鎖定。您可能需要釋放讀取鎖定作爲putInSet()中的第一行,然後在釋放寫入鎖定之前重新獲取finally中的讀取鎖定。 – InverseFalcon 2011-09-16 23:56:00

6

您可以使用Collections.unmodifiableSet創建該設備的只讀視圖。只需將此視圖傳遞給不需要寫入集合的所有人即可。 (對於任何試圖修改此視圖的人,都將引發UnsupportedOperationException)。

1

這是一個有趣的問題,通常情況下是相反的。

如果你想要一個不變的映射,直到某個魔術方法告訴應用程序的其餘部分它可以,那麼可以使用Collections.unmodifiableMap()在初始化後創建映射的不可變副本。

當magic方法運行時,它可以用一個可修改的副本再次替換地圖。

Map myMap; 

public MyClass(Map myMap) { 
    this.myMap = Collections.unmodifiableMap(myMap); 
} 

synchronized public void releaseMyMap() { 
    myMap = new HashMap(myMap); 
} 
0

您可以從一個集合擴展並提供您自己的基於鎖定的實現(添加)讀取和寫入集合。

這將確保無論何時一個線程正在讀取(在獲取鎖定之後),其他線程都不能寫入它。

0

不完全確定問題所在,但如果您只是試圖避免使用HashSet訪問併發問題,可能值得看看ConcurrentSkipListSet。大部分操作需要log(n)時間,但不需要同步,並且不會在插入,刪除和訪問操作時阻塞。在整體上可能會給你更好的表現。