在Java中锁定一个hashset

时间:2010-10-11 17:19:26

标签: java locking hashset

我的代码中有一个静态的HashSet对象引用,它必须禁止所有写入请求,直到给定的方法运行(它仅将hashset用于读取目的)。我已经阅读了Thread基础知识,但我还不清楚如何继续这样做。

有人可以帮帮我吗?

5 个答案:

答案 0 :(得分:9)

你提到你已经阅读了Thread基础知识,所以我假设你有一个多线程应用程序,你有多个读者和/或编写者。您可以使用读写锁来限制对集合的访问。当给定方法执行时,它锁定读锁定,允许其他人读取但不写入。只要您使用下面的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();
    }
 }

答案 1 :(得分:6)

您可以使用Collections.unmodifiableSet创建该集的只读视图。只需将此视图传递给不需要写入集合的所有人。 (对于试图修改此视图的任何人,将抛出UnsupportedOperationException。)

答案 2 :(得分:1)

这是一个有趣的问题,通常是另一种方式。

如果你想要一个不可变的地图,直到某个魔术方法告诉应用程序的其余部分它没问题,你可以使用Collections.unmodifiableMap()在初始化后创建地图的不可变副本。

当魔术方法运行时,它可以再次用可修改的副本替换地图。

Map myMap;

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

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

答案 3 :(得分:0)

您可以从Set扩展并提供您自己的基于锁的实现(添加)来读取和写入Set。

这将确保无论何时线程正在读取(获取锁定后),其他线程都无法写入。

答案 4 :(得分:0)

不确定是什么问题,但是如果你只是试图避免使用HashSet访问并发问题,那么可能值得查看ConcurrentSkipListSet。大多数操作需要log(n)时间,但它不需要同步,也不会阻止插入,删除和访问操作。在整体上可能会给你更好的表现。