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

我正在寻找一个高效的系统来分层组织一系列读/写锁来管理对分层组织资源的访问.如果一个子树被锁定以进行写入,那么在整个子树中都不能获得其他锁定,直到它被释放为止;类似地,子树中的写锁定应该防止锁定父节点.

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

>使用Apache Commons Transaction.不幸的是,该项目自2008年3月以来一直没有更新,并且已经非正式终止.一些api文档似乎表明即将推出的版本(1.3或2.0)将包括some kind of hierarchical locking,但是无法找到源代码,似乎我们无法再访问其SVN存储库.
>使用一系列ReentrantReadWriteLocks,我将按层次结构组织.我不是并发专家,而且我有点害怕自己这样做.初步的想法似乎表明,即使在我尝试锁定子树之前,我必须在管理reentrantreadwritelocks本身的整个结构上使用外部锁 – 这样即使释放锁,我也必须使用外部锁…
>使用java.util.concurrentjava.util.concurrent.atomic中的类以比使用一系列reentrantreadwritelocks更有效的方式实现我的分层锁定.

我已经准备好走最后一条路,但我很惊讶没有找到任何可以更好地解决这个问题的现有库.所以:

>我错过了一些明显的解决方案吗?
>或者这个问题特别难以解决

解决方法

我不知道我是否理解你的问题,正如你所说当你锁定一个子树进行写入时,整个结构都被锁定了.
因此,简单的解决方案是为整个结构设置一个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;
}

如果无法获取任何锁定,则解锁锁定的内容并稍后重试(可以使用全局条件变量,超时等来实现此目的).

编辑:添加代码以读取锁定/写入锁定树

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


应用场景 C端用户提交工单、工单创建完成之后、会发布一条工单创建完成的消息事件(异步消息)、MQ消费者收到消息之后、会通知各处理器处理该消息、各处理器处理完后都会发布一条将该工单写入搜索引擎的消息、最终该工单出现在搜索引擎、被工单处理人检索和处理。 事故异常体现 1、异常体现 从工单的流转记录发现、
线程类,设置有一个公共资源 package cn.org.chris.concurrent; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * @Descrip
Java中的数字(带有0前缀和字符串)
在Java 9中使用JLink的目的是什么?
Java Stream API Filter(过滤器)
在Java中找到正数和负数数组元素的数量
Java 9中JShell中的不同启动脚本是什么?
使用Java的位填充错误检测技术
java中string是什么
如何使用Java中的JSON-lib API将Map转换为JSON对象?
Java菜单驱动程序以检查数字类型
使用Junit的Maven项目 - 检查银行账号
JAVA编程基础
在Java中使用throw、catch和instanceof来处理异常
在Java中,将数组分割为基于给定查询的子数组后,找到子数组的最大子数组和
如何在Java中从给定的字符串中删除HTML标签?
在PHP中,IntlChar getBlockCode()函数的翻译如下:
如何在Android中实现按下返回键再次退出的功能?
如何使用Java中的流式API解析JSON字符串?
Java中的模式类