首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java中的分层互斥锁

Java中的分层互斥锁
EN

Stack Overflow用户
提问于 2012-02-16 05:23:08
回答 2查看 1.3K关注 0票数 12

我希望能够基于文件系统层次结构进行锁定。例如:

线程1:

代码语言:javascript
复制
lock("/");
doStuff();
unlock();

线程2:

代码语言:javascript
复制
lock("/sub/foo");
doStuff();
unlock();

线程3:

代码语言:javascript
复制
lock("/sub/bar");
doStuff();
unlock();

如果线程1首先获得锁,那么线程2和3将被阻塞,直到线程1解锁。但是,如果线程2首先获得锁,那么线程3应该能够与线程2同时执行。一般规则是,如果父目录上有锁,则线程必须阻塞。

Java有没有内置的东西可以帮助解决这个问题呢?我希望避免为每个目录存储一个锁,因为将会有数十万个目录。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-02-16 05:58:14

我将目录路径存储在树中,如下所示:

代码语言:javascript
复制
- /
 - sub
  - foo
  - bar

每当您需要锁定该树中的任何内容时,您都可以从根节点向下移动,并获取除目标节点本身以外的所有内容的读锁定。目标节点获得一个写锁。

这个方案保证了树的相关部分的死锁自由和稳定性。

我不认为存储数十万个锁有什么特别的问题。这可能会在每个锁上浪费100字节的RAM。但它简化了架构。你有没有衡量它是否真的是一个问题?

作为另一种选择,你可以有一个从路径到锁的映射。该字典上的所有操作都必须由调用方同步。这允许您懒惰地初始化锁。您还可以定期垃圾收集未使用的锁,方法是首先在根上设置一个写锁,这会使所有操作停顿。一旦一切都安静下来,你就丢弃了所有的非root锁。

票数 8
EN

Stack Overflow用户

发布于 2012-02-16 06:18:12

也许有一个性能更好的解决方案,但这里是我如何开始的。

我将创建一个具有lock(path)unlock(path)方法的共享TreeAccess对象。此方法必须进入一个同步块,该块将循环,直到路径可用。在每次迭代中,如果不可用,它将检查路径是否可用,如果不可用,则执行wait(),直到其他线程调用notifyAll()。如果路径可用,则它将继续,完成后,调用unlock()方法,该方法将执行notifyAll()

在继续之前,您必须将锁定的路径存储到某个数据结构中。在通知之前,您必须从该数据结构中删除未锁定的路径。要检查路径是否可用,您需要查找此数据结构中是否存在与您要锁定的路径相等的路径,或者该路径是您想要锁定的路径的祖先。

代码语言:javascript
复制
public void lock(String path) {
    synchronized (lock) {
        while (!available(path)) {
            lock.wait();
        }
        lockedPaths.add(path);
    }
}

public void unlock(String path) {
    synchronized (lock) {
        lockedPaths.remove(path);
        lock.notifAll();
    }
}

private boolean available(String path) {
    for (String lockedPath : lockedPaths) {
        if (isParentOrEqual(lockedPath, path) { // this method is left as an exercise
            return false;
        }
    }
    return true;
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9301631

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档