StampedLock源码分析


title: JUC.StampedLock

StampedLock提纲

StampedLock简介

首先大方向看下StampedLock类图
avatar
从图中可以看出这个锁貌似有点屌屌的有读锁写锁读写锁。这个锁看上去很厉害,其实这个锁不像其它锁那么安全使用,存在很高的风险性。
听说该锁设计之初是为了作为工具类开发其它线程安全组件,用好了提升性能。没用好会发生死锁,CPU飙升耗死资源的情况,以及读写锁脏数据
为什么出现死锁,如果记得我前一章所写的非可重入锁就知道了。这个大哥也是非可重入的,哈哈哈~

至于CPU飙升引用一文章地址* https://m.aliyun.com/yunqi/articles/20340,然后我再解释一下。因为文中老哥没有解释为啥。
当线程被中断的时候被park的线程会继续进入到循环中不断的获取锁到满足条件为止,导致CPU爆炸。
后面我有时间会详细写一篇关于这个问题的文章,以及相比较我引用文章更好理解的例子。
读写锁的脏数据是因为读的时候数据被修改了,不过可以通过貌似有个官方的代码模板的写法可以解决。
就是先使用乐观锁,然后再转为读锁,不让数据被修改了。
在下面我放上了实例代码。
上面介绍了这个锁以及使用风险,咱们继续说说使用场景。
读写锁可以应用在应用缓存方面,比如一方面写一方面缓存数据,并提供读取缓存。

 * 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 != 0L) {
 *           stamp = ws;
 *           x = newX;
 *           y = newY;
 *           break;
 *         }
 *         else {
 *           sl.unlockRead(stamp);
 *           stamp = sl.writeLock();
 *         }
 *       }
 *     } finally {
 *       sl.unlock(stamp);
 *     }
 *   }
 * }}

原理剖析

理论上来说StampedLock锁本质上还是基于CAS以及双向队列实现,换汤不换药。这里还是佩服一下 Doug Lea大师。大师对于数据结构的运用还是挺秀的源码都挺好看。

  • 写锁
    writeLock是一个独占锁某时只允许一个线程修改。当前没有读锁或者写锁的时候才可以获取,请求的时候会返回一个stamp标识该锁版本释放的时候需要传入。
  • 读锁
    readLock是一个共享锁,当前没有写锁的时候可以多个线程获取,如果有写锁存在则会造成阻塞。
  • 读写锁
    tryOptimisticRead并没有使用CAS修改锁的状态,仅仅通过位运算测试。如果当前没有线程持有写锁,则简单的返回要给非0的stamp信息。获取stamp后再具体操作数据前还需要调用validate
    验证stamp是否已经不可用,也就是看是否tryOptmisticRead返回stamp期间是否有线程持有了写锁。
    这一章我源代码看的不多,所以写不出什么深入的东西。后续我会持续更新这一章~

欢迎扫码加入知识星球继续讨论
avatar

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值