在Java中使用什么策略进行分层可重入的读/写锁定?

| 我正在寻找一个高效的系统,以使其具有一系列按层次结构组织的读/写锁,以管理对按层次结构组织的资源的访问。如果一个子树被锁定以进行写操作,那么在整个子树中,除非释放它,否则将无法获得其他任何锁定;同样,子树中的写锁定应防止锁定父级。 这是我正在考虑的想法: 使用Apache Commons Transaction。不幸的是,该项目自2008年3月以来未进行任何更新,并且已非正式终止。一些API文档似乎表明即将发布的版本(1.3或2.0)将包含某种类型的层次结构锁定,但是在任何地方都找不到源,而且似乎我们无法再访问其SVN存储库。 使用一系列的“ 0”,我将对其进行分层组织。我不是并发专家,我有点害怕自己做。初步的想法似乎表明,即使在尝试锁定子树之前,我也必须在管理ѭ0本身的整个结构上使用外部锁-因此,即使是释放锁,我也必须使用外锁… 使用
java.util.concurrent
java.util.concurrent.atomic
中的类以比一系列
ReentrantReadWriteLock
更为有效的方式实现我的层次结构锁。 我已经准备好走最后一条路,但是我很惊讶地没有找到任何可以更好地解决此问题的现有库。所以: 我错过了一些明显的解决方案吗? 还是这个问题很难正确解决?     
已邀请:
        我不知道我是否很好地理解了您的问题,正如您所说的那样,当您锁定一个子树进行写入时,整个结构都被锁定了。 因此,简单的解决方案是为整个结构设置一个RW锁。 顺便说一句,
java.util.concurrent.atomic
不会帮您多过一堆RW锁。 如果您希望能够独立地锁定同级,则可以采用第二种解决方案(一棵锁树,其中每个节点都引用其父级)。 锁定节点将使用其写入锁定来锁定它,并使用读取锁定来锁定每个父节点。 父项不能在孩子被锁定时被锁定,因为您不能像锁定孩子已获得读锁定那样获得其写锁定。 仅当没有其他线程对任何父对象进行写锁定时,才可以锁定孩子。 上述锁是排他锁。 (读写锁的另一个名称是共享独占锁) 要添加共享锁,每个节点还需要一个原子整数,指示: 如果为正,则为间接写锁子代数;如果为负,则节点已被读取锁定的次数。 同样,节点及其父节点将被读取锁定,以避免在父节点上获取新的写锁定。 伪代码:
Node {
    // fields
    parent: Node
    lock: RWLock
    count: AtomicInteger
}

public boolean trylocktree(node: Node, exclusive: boolean) {
    if (exclusive) {
        return trylocktree_ex(node, true);
    } else {
        return trylocktree_sh(node);
    }
}
private boolean switch_count(i: AtomicInteger, diff: int) {
    // adds diff to i if the sign of i is the same as the sign of diff
    while (true) {
        int v = i.get();
        if (diff > 0 ? v < 0 : v > 0)
            return false;
        if (i.compareAndSet(v, v + diff))
            return true;
    }
}
private boolean trylocktree_ex(node: Node, writing: boolean) {
    // check if a node is read-locked
    if (!switch_count(node.count, 1))
        return false;
    // lock using the lock type passed as an arg
    if (!node.lock(writing).trylock()) {
        node.count--;
        return false;
    }
    // read-lock every parent
    if (!trylocktree_ex(node.parent, false)) {
        node.count--
        node.lock(writing).unlock();
        return false;
    }
    return true;
}
private boolean trylocktree_sh(node: Node) {
    // mark as shared-locked subtree
    if (!switch_count(node.count, -1))
        return false;
    // get shared-lock on parents
    if (!readlock_recursively(node)) {
        node.count++;
        return false;
    }
    return true;
}
private boolean readlock_recursively(node: Node) {
    if (!node.lock(false).trylock())
        return false;
    if (!readlock_recursively(node.parent)) {
        node.lock(false).unlock();
        return false;
    }
    return true;
}
如果无法获取任何锁定,则可以解锁已锁定的内容,然后稍后重试(可以使用全局条件变量,超时等来实现此目的)。 编辑:添加代码以读取锁定/写入锁定树     
        我将寻求您自己的解决方案,并以Apache Apache Commons Transaction Algorithm给出的算法为起点。 您可以使用ReentrantReadWriteLock,尽管通常此锁更适合一种生产者很多读者案例的模式,这可能不是您想要的。看来您的锁更像是常规的可重入互斥锁。     

要回复问题请先登录注册