2010-10-11 142 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)时间,但不需要同步,并且不会在插入,删除和访问操作时阻塞。在整体上可能会给你更好的表现。