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
    评论
[JAVA工程师必会知识点之并发编程]1、现在几乎100%的公司面试都必须面试并发编程,尤其是互联网公司,对于并发编程的要求更高,并发编程能力已经成为职场敲门砖。2、现在已经是移动互联和大数据时代,对于应用程序的性能、处理能力、处理时效性要求更高了,传统的串行化编程无法充分利用现有的服务器性能。3、并发编程是几乎所有框架的底层基础,掌握好并发编程更有利于我们学习各种框架。想要让自己的程序执行、接口响应、批处理效率更高,必须使用并发编程。4、并发编程是中高级程序员的标配,是拿高薪的必备条件。 【主讲讲师】尹洪亮Kevin:现任职某互联网公司首席架构师,负责系统架构、项目群管理、产品研发工作。10余年软件行业经验,具有数百个线上项目实战经验。擅长JAVA技术栈、高并发高可用伸缩式微服务架构、DevOps。主导研发的蜂巢微服务架构已经成功支撑数百个微服务稳定运行【推荐你学习这门课的理由:知识体系完整+丰富学习资料】1、 本课程总计122课时,由五大体系组成,目的是让你一次性搞定并发编程。分别是并发编程基础、进阶、精通篇、Disruptor高并发框架、RateLimiter高并发访问限流吗,BAT员工也在学。2、课程附带附带3个项目源码,几百个课程示例,5个高清PDF课件。3、本课程0基础入门,从进程、线程、JVM开始讲起,每一个章节只专注于一个知识点,每个章节均有代码实例。 【课程分为基础篇、进阶篇、高级篇】一、基础篇基础篇从进程与线程、内存、CPU时间片轮训讲起,包含线程的3种创建方法、可视化观察线程、join、sleep、yield、interrupt,Synchronized、重入锁、对象锁、类锁、wait、notify、线程上下文切换、守护线程、阻塞式安全队列等内容。二、进阶篇进阶篇课程涵盖volatied关键字、Actomic类、可见性、原子性、ThreadLocal、Unsafe底层、同步类容器、并发类容器、5种并发队列、COW容器、InheritableThreadLocal源码解析等内容。三、精通篇精通篇课程涵盖JUC下的核心工具类,CountDownLath、CyclicBarrier、Phaser、Semaphore、Exchanger、ReentrantLock、ReentrantReadWriteLockStampedLockLockSupport、AQS底层、悲观锁、乐观锁、自旋锁、公平锁、非公平锁、排它锁、共享锁、重入锁、线程池、CachedThreadPool、FixedThreadPool、ScheduledThreadPool、SingleThreadExecutor、自定义线程池、ThreadFactory、线程池切面编程、线程池动态管理等内容,高并发设计模式,Future模式、Master Worker模式、CompletionService、ForkJoin等课程中还包含Disruptor高并发无锁框架讲解:Disruptor支持每秒600万订单处理的恐怖能力。深入到底层原理和开发模式,让你又懂又会用。高并发访问限流讲解:涵盖木桶算法、令牌桶算法、Google RateLimiter限流开发、Apache JMeter压力测试实战。 【学完后我将达到什么水平?】1、 吊打一切并发编程相关的笔试题、面试题。2、 重构自己并发编程的体系知识,不再谈并发色变。3、 精准掌握JAVA各种并发工具类、方法、关键字的原理和使用。4、 轻松上手写出更高效、更优雅的并发程序,在工作中能够提出更多的解决方案。  【面向人群】1、 总感觉并发编程很难、很复杂、不敢学习的人群。2、 准备跳槽、找工作、拿高薪的程序员。3、 希望提高自己的编程能力,开发出更高效、性能更强劲系统的人群。4、 想要快速、系统化、精准掌握并发编程的人群。【课程知识体系图】
StampedLock 是 Java 8 引入的一种新的锁机制,它是 ReentrantReadWriteLock 的改进版本,提供了更高级别的并发控制。 StampedLock 主要有三种模式:读模式、写模式和乐观读模式。 1. 读模式(Read Mode):多个线程可以同时获取读锁,只要没有线程持有写锁。读锁是共享的,可以提供高并发性。 2. 写模式(Write Mode):写锁是独占的,当一个线程持有写锁时,其他线程无法获取读锁或写锁,保证了数据的一致性。 3. 乐观读模式(Optimistic Read Mode):乐观读是一种特殊的读模式,不需要获取锁。在乐观读之前,先获取一个标记(stamp),然后在验证数据是否被修改的过程中,数据是不受保护的。如果数据没有被修改,则认为读取成功,否则需要重新尝试。乐观读适用于读操作频繁、写操作较少的场景。 StampedLock 的使用示例如下: ```java import java.util.concurrent.locks.StampedLock; public class Example { private final StampedLock lock = new StampedLock(); private int x; private int y; public void writeData(int newX, int newY) { long stamp = lock.writeLock(); try { x = newX; y = newY; } finally { lock.unlockWrite(stamp); } } public double readDistanceFromOrigin() { long stamp = lock.tryOptimisticRead(); int currentX = x; int currentY = y; if (!lock.validate(stamp)) { stamp = lock.readLock(); try { currentX = x; currentY = y; } finally { lock.unlockRead(stamp); } } return Math.sqrt(currentX * currentX + currentY * currentY); } } ``` 在示例中,我们使用 StampedLock 来保护数据的读写操作。writeData() 方法通过 writeLock() 获取写锁,然后修改数据。readDistanceFromOrigin() 方法使用了乐观读模式,首先尝试获取一个标记(stamp),然后读取数据并计算距离。如果在验证数据的过程中发现数据已被修改,就需要重新获取读锁。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值