• Java并发编程原理与实战三十九:JDK8新增锁StampedLock详解


    1、StampedLock是做什么的?

    -----》它是ReentrantReadWriteLock 的增强版,是为了解决ReentrantReadWriteLock的一些不足。
     
    2、ReentrantReadWriteLock有什么不足之处呢?
    ------》我们都知道,ReentrantReadWriteLock是读写锁,在多线程环境下,大多数情况是读的情况远远大于写的操作,因此可能导致写的饥饿问题。(换人话来说的话,读操作一直都能抢占到CPU时间片,而写操作一直抢不了)
     
    3、为什么会导致写操作会出血饥饿问题呢?
    -----》ReentrantReadWriteLock写锁的互斥的
    (读和读---不互斥,读和写---互斥,写和写----互斥),懂了吗?
     
    4、正因为ReentrantReadWriteLock出现了读和写是互斥的情况,这个地方需要优化,因此就出现了StampedLock!
     
    5、StampedLock是读锁并不会阻塞写锁。这里就有朋友会问,如果这样设计的话,那么怎样保证读和写的一致性呢?
    -----》StampedLock的设计思路也比较简单,就是在读的时候发现有写操作,再去读多一次。(思想上来说)
     
    6、那下一个问题就是StampedLock是怎样知道读的时候发生了写操作呢?
    -----》我们的StampedLock有两种锁,一种是悲观锁,另外一种是乐观锁。如果线程拿到乐观锁就读和写不互斥,如果拿到悲观锁就读和写互斥。
     
    7、看StampedLock源码的时候,可以看writeLock()和trywriteLock(),tryOptimisticRead()这是本API中最有亮点的方法(乐观锁)。
     
     
    ==============================================================
     
     
    public class Demo {
    private int balance;
    private StampedLock lock = new StampedLock();
    public void conditionReadWrite (int value) {
    // 首先判断balance的值是否符合更新的条件
    long stamp = lock.readLock();
    while (balance > 0) {
    long writeStamp = lock.tryConvertToWriteLock(stamp);
    if(writeStamp != 0) { // 成功转换成为写锁
    stamp = writeStamp;
    balance += value;
    break;
    } else {
    // 没有转换成写锁,这里需要首先释放读锁,然后再拿到写锁
    lock.unlockRead(stamp);
    // 获取写锁
    stamp = lock.writeLock();
    }
      }
    lock.unlock(stamp);
    }
    public void optimisticRead() {
    long stamp = lock.tryOptimisticRead();
    int c = balance;
    // 这里可能会出现了写操作,因此要进行判断
    if(!lock.validate(stamp)) {
    // 要从新读取
    long readStamp = lock.readLock();
    c = balance;
    stamp = readStamp;
    }
    /// 
    lock.unlockRead(stamp);
    }
    public void read () {
    long stamp = lock.readLock();
    lock.tryOptimisticRead();
    int c = balance;
    // ...
    lock.unlockRead(stamp);
    }
    public void write(int value) {
    long stamp = lock.writeLock();
    balance += value;
    lock.unlockWrite(stamp);
    }
     
    }
     
    ====================================================
     
    StampedLock的性能是远远好过ReentrantReadWriteLock的。那为什么还存在ReentrantReadWriteLock呢?
    ------》根据我们上述的代码,我们知道使用StampedLock,编写代码上相对繁琐些。ReentranReadWriteLock比较简单些。
     
     
    悲观锁:每次拿数据的时候就去锁上。
    乐观锁:每次去拿数据的时候,都没锁上,而是判断标记位是否有被修改,如果有修改就再去读一次。
    (就像很多个人去桌子上看今天老师布置的作业题,另外桌子旁边有一个牌子,红色面代表“作业题已经被修改过了”,白色面代表“题目是最新的”。第一个人去看作业题,再看了下牌子,牌子是白色的,作业题是最新的。但是有一个人去看作业题,看完之后,再看隔壁的牌子,牌子变成红色了,于是他赶紧回去看了一下题目,果然题目已经被改过了,于是他再看了一次,再确认一次牌子颜色,都没问题之后,就放心走了。)

     

  • 相关阅读:
    jquery操作select(取值,设置选中)
    jQuery懒加载插件 – jquery.lazyload.js简单调用
    js获取URL中的参数
    数据结构之队列C++版
    数据结构之堆栈java版
    数据结构之堆栈C++版
    c++操作符重载
    QT状态机
    c++/c关于函数指针
    学习Qt的一点小感想
  • 原文地址:https://www.cnblogs.com/pony1223/p/9552093.html
Copyright © 2020-2023  润新知