美文网首页工作生活
新特性13-StampedLock

新特性13-StampedLock

作者: 三秋十里 | 来源:发表于2019-07-04 16:11 被阅读0次

       看到这个,忍不住有点激动人心。没有人喜欢在代码中使用同步,它会让你的程序效率更低,而且严重的还可能会引起程序崩溃。尽管如此,有时候我们还是不得不使用它。

       当多个进程访问一个资源的时候,有多种方法可以进行同步。其中用得最多的一种是ReadWriteLock以及基于它的几种实现。它通过阻塞写线程的方式来允许多个线程并发的读,这样减少了线程之间的竞争。听起来还不错,但实际上这个锁实在是太慢了,尤其是当有许多写线程的时候。

       值得高兴的是,现在Java 8中推出了一个新的读写锁,名字叫StampedLock。StampedLock不仅读写更快,而且还提供了很多强大的API来创建乐观锁。这样如果没有写操作在访问临界区域的话,你只需很低的开销就能获取到一个读锁。访问结束后你可以查询锁来判断这期间是否发生了写操作,如果有的话再选择进行重试,升级锁,或者放弃这个操作。

       ReentrantReadWriteLock 在沒有任何读写锁时,才可以取得写入锁,这可用于实现了悲观读取(Pessimistic Reading),即如果执行中进行读取时,经常可能有另一执行要写入的需求,为了保持同步,ReentrantReadWriteLock 的读取锁定就可派上用场。

       然而,如果读取执行情况很多,写入很少的情况下,使用 ReentrantReadWriteLock 可能会使写入线程遭遇饥饿(Starvation)问题,也就是写入线程吃吃无法竞争到锁定而一直处于等待状态。

       StampedLock控制锁有三种模式(写,读,乐观读),一个StampedLock状态是由版本和模式两个部分组成,锁获取方法返回一个数字作为票据stamp,它用相应的锁状态表示并控制访问,数字0表示没有写锁被授权访问。在读锁上分为悲观锁和乐观锁。

       所谓的乐观读模式,也就是若读的操作很多,写的操作很少的情况下,你可以乐观地认为,写入与读取同时发生几率很少,因此不悲观地使用完全的读取锁定,程序可以查看读取资料之后,是否遭到写入执行的变更,再采取后续的措施(重新读取变更信息,或者抛出异常) ,这一个小小改进,可大幅度提高程序的吞吐量!!

下面是java doc提供的StampedLock一个例子

class Point {
    private double x, y;
    private final StampedLock sl = new StampedLock();
    void move(double deltaX, double deltaY) { // an exclusively locked method
            long stamp = sl.writeLock();
            try {
                x += deltaX;
                y += deltaY;
            } finally {
                sl.unlockWrite(stamp);
            }
        }

    //下面看看乐观读锁案例
    double distanceFromOrigin() { // A read-only method
            long stamp = sl.tryOptimisticRead(); //获得一个乐观读锁
            double currentX = x, currentY = y; //将两个字段读入本地局部变量
            if (!sl.validate(stamp)) { //检查发出乐观读锁后同时是否有其他写锁发生?
                stamp = sl.readLock(); //如果没有,我们再次获得一个读悲观锁
                try {
                    currentX = x; // 将两个字段读入本地局部变量
                    currentY = y; // 将两个字段读入本地局部变量
                } finally {
                    sl.unlockRead(stamp);
                }
            }
            return Math.sqrt(currentX * currentX + currentY * currentY);
        }

    /**
     * 下面是悲观读锁案例
     */
    void moveIfAtOrigin(double newX, double newY) { // upgrade
        // Could instead start with optimistic, not read mode
        long stamp = sl.readLock();
        try {
            while (x == 0.0 && y == 0.0) { //循环,检查当前状态是否符合
                long ws = sl.tryConvertToWriteLock(stamp); //将读锁转为写锁
                if (ws != 0 L) { //这是确认转为写锁是否成功
                    stamp = ws; //如果成功 替换票据
                    x = newX; //进行状态改变
                    y = newY; //进行状态改变
                    break;
                } else { //如果不能成功转换为写锁
                    sl.unlockRead(stamp); //我们显式释放读锁
                    stamp = sl.writeLock(); //显式直接进行写锁 然后再通过循环再试
                }
            }
        } finally {
            sl.unlock(stamp); //释放读锁或写锁
        }
    }
}

相关文章

  • 新特性13-StampedLock

    看到这个,忍不住有点激动人心。没有人喜欢在代码中使用同步,它会让你的程序效率更低,而且严重的还可能会引起程序崩溃。...

  • JDK新特性书目录

    JDK1.4新特性 JDK1.5新特性 JDK1.6新特性 JDK1.7新特性 JDK1.8新特性

  • Math方法和es新特性

    es6常用 es7新特性 es8新特性 es9新特性 es10新特性

  • Java11的新特性

    Java语言特性系列 Java5的新特性 Java6的新特性 Java7的新特性 Java8的新特性 Java9的...

  • Java15的新特性

    Java语言特性系列 Java5的新特性 Java6的新特性 Java7的新特性 Java8的新特性 Java9的...

  • Java12的新特性

    Java语言特性系列 Java5的新特性 Java6的新特性 Java7的新特性 Java8的新特性 Java9的...

  • iOS9、iOS10新特性

    iOS10新特性、iOS9新特性

  • Xcode 11.4 新特性概览

    Xcode 11.4 新特性概览Xcode 11.4 新特性概览

  • 【一起来烧脑】一步学会TypeScript入门

    字符串新特性变量和参数新特性函数新特性匿名函数for of循环TypeScript语言中的面向对象特性 理解ES5...

  • 新特性

    //判断是属于测试还是应用 //#define X using System; using System.Diag...

网友评论

    本文标题:新特性13-StampedLock

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