美文网首页
StampedLock更好的读写锁(gold_axe)

StampedLock更好的读写锁(gold_axe)

作者: 胖达_4b7e | 来源:发表于2020-10-28 17:48 被阅读0次

JDK8引入
主要是有乐观读, 就是完全无锁, 读到以后再去检查下版本, 不行再说

好处

ReentrantReadWriteLock 的改进就是加了乐观读, 这样了避免了 ReentrantReadWriteLock 非公平锁时 读多写少, 写入队以后一直轮不到,饿死的情况, 还提高了吞吐量

另外, 可以升级 也可以降级

坏处

ReentrantReadWriteLock 比, 功能少了, 只是一个子集

  • 不支持条件变量
  • 不能中断线程
  • 不能重入

而且 ,本来是为内部使用的, 用起来一定要按模板,比较复杂

乐观读

不能保证读到是最新的, 可以拿到以后再验证, 完全无锁, 性能好

使用 都是这个模板

   public String get(Integer key) {
        // 1. 尝试通过乐观读模式读取数据,非阻塞
        long stamp = lock.tryOptimisticRead();
        // 2. 读取数据到当前线程栈
        String currentValue = idMap.get(key);
        // 3. 校验是否被其他线程修改过,true 表示未修改,否则需要加悲观读锁
        if (!lock.validate(stamp)) {
            // 4. 上悲观读锁,并重新读取数据到当前线程局部变量
            stamp = lock.readLock();
            try {
                currentValue = idMap.get(key);
            } finally {
                lock.unlockRead(stamp);
            }
        }
        // 5. 若校验通过,则直接返回数据
        return currentValue;
    }

原理

ReentrantReadWriteLock 性能要高,内部没用AQS 但是 和AQS原理是一样的 都是用的 CLH队列


一样是双向链表, 有存了 头尾 字段, 有个状态state
也是状态2 用, 又表示写锁又记读锁

注意有个NCPU字段, 记录的是核数, 如果核数>1 , 获取锁和入队 都有自旋

CLH队列的节点比AQS更加简单, 只有3种状态


另外多了一个 cowait字段, 记录读线程, 头插法


这样 如果前一个节点就是读, 下一个读就连入cowait了, 不像AQS往后连,
而且因为是头插法, 晚来的读 反而先叫起来, 不过反正不读之间不阻塞, 差不多

得锁 解锁

获取写锁:



cas试试, 失败就入队,

入队有大量自旋操作, 就是入前文所述的 CLH

读锁也差不多

释放锁:
ReentrantReadWriteLock 差不多 都改state, 叫醒队列下一个, 就是前面多了一步, 核对传入的stamp, 如果对不上会抛出异常

相关文章

网友评论

      本文标题:StampedLock更好的读写锁(gold_axe)

      本文链接:https://www.haomeiwen.com/subject/ckhzmktx.html