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

我正在寻找高效的系统,让一系列读/写锁分层管理,以管理对分层组织资源的访问。 如果一个子树被锁定写入,那么在整个子树中都不能获得其他锁,直到它被释放; 同样,子树中的写入锁应该防止锁定在父项中。

以下是我正在考虑的想法:

  • 使用Apache Commons Transaction 。 不幸的是,该项目自2008年3月以来一直未更新,并已非正式终止。 一些API文档似乎表明版本即将到来(1.3或2.0)将包含某种分层锁定,但无法找到源,看起来我们无法再访问其SVN存储库。

  • 使用一系列ReentrantReadWriteLock ,我将按层次组织。 我不是并发专家,我有点害怕自己做这件事。 初步想法似乎表明,即使在我可以尝试锁定子树之前,我也必须在管理ReentrantReadWriteLock本身的整个结构上使用外部锁 - 因此,即使释放锁,我也必须使用外部锁锁…

  • 使用java.util.concurrentjava.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,虽然通常这个锁适合一个生产者的模式 - 许多读者可能不是你正在寻找的东西。 看起来你的锁更像是一个普通的可重入互斥锁。

    链接地址: http://www.djcxy.com/p/7199.html

    上一篇: What strategy to use in Java for hierarchical reentrant read/write locking?

    下一篇: MediaElement disrupting Audio Podcast (MediaPlayer) in WP7