悲观读/写锁示例

final StampedLock sl = new StampedLock();// 获取 / 释放悲观读锁示意代码
long stamp = sl.readLock();
try {// 省略业务相关代码
} finally {sl.unlockRead(stamp);
}// 获取 / 释放写锁示意代码
long stamp = sl.writeLock();
try {// 省略业务相关代码
} finally {sl.unlockWrite(stamp);
}

乐观读失效,升级为悲观读

public class Point {private int x, y;final StampedLock sl = new StampedLock();// 计算到原点的距离  int distanceFromOrigin() {// 乐观读long stamp = sl.tryOptimisticRead();// 读入局部变量,// 读的过程数据可能被修改int curX = x, curY = y;// 判断执行读操作期间,// 是否存在写操作,如果存在,// 则 sl.validate 返回 falseif (!sl.validate(stamp)){// 升级为悲观读锁stamp = sl.readLock();try {curX = x;curY = y;} finally {// 释放悲观读锁sl.unlockRead(stamp);}}return Math.sqrt(curX * curX + curY * curY);}
}

有一点需要特别注意,那就是:如果线程阻塞在 StampedLock 的 readLock() 或者 writeLock() 上时,此时调用该阻塞线程的 interrupt() 方法,会导致 CPU 飙升。例如下面的代码中,线程 T1 获取写锁之后将自己阻塞,线程 T2 尝试获取悲观读锁,也会阻塞;如果此时调用线程 T2 的 interrupt() 方法来中断线程 T2 的话,你会发现线程 T2 所在 CPU 会飙升到 100%。

final StampedLock lock= new StampedLock();
Thread T1 = new Thread(()->{// 获取写锁lock.writeLock();// 永远阻塞在此处,不释放写锁LockSupport.park();
});
T1.start();
// 保证 T1 获取写锁
Thread.sleep(100);Thread T2 = new Thread(()->// 阻塞在悲观读锁lock.readLock()
);
T2.start();
// 保证 T2 阻塞在读锁
Thread.sleep(100);
// 中断线程 T2
// 会导致线程 T2 所在 CPU 飙升
T2.interrupt();
T2.join();

StampedLock 读模板:

final StampedLock sl = new StampedLock();// 乐观读
long stamp = sl.tryOptimisticRead();
// 读入方法局部变量
......
// 校验 stamp
if (!sl.validate(stamp)){// 升级为悲观读锁stamp = sl.readLock();try {// 读入方法局部变量.....} finally {// 释放悲观读锁sl.unlockRead(stamp);}
}
// 使用方法局部变量执行业务操作
......

StampedLock 写模板:

long stamp = sl.writeLock();
try {// 写共享变量......
} finally {sl.unlockWrite(stamp);
}

Java并发编程实战~StampedLock相关推荐

  1. 【极客时间】《Java并发编程实战》学习笔记

    目录: 开篇词 | 你为什么需要学习并发编程? 内容来源:开篇词 | 你为什么需要学习并发编程?-极客时间 例如,Java 里 synchronized.wait()/notify() 相关的知识很琐 ...

  2. 《Java 并发编程实战》--读书笔记

    Java 并发编程实战 注: 极客时间<Java 并发编程实战>–读书笔记 GitHub:https://github.com/ByrsH/Reading-notes/blob/maste ...

  3. Java并发编程实战笔记2:对象的组合

    设计线程安全的类 在设计现车让安全类的过程之中,需要包含以下三步: 找出构成对象状态的所有变量 找出约束状态变量的不变性条件 建立对象状态的并发访问策略 实例封闭 通过封闭机制与合适的加锁策略结合起来 ...

  4. aqs clh java_【Java并发编程实战】—– AQS(四):CLH同步队列

    在[Java并发编程实战]-–"J.U.C":CLH队列锁提过,AQS里面的CLH队列是CLH同步锁的一种变形. 其主要从双方面进行了改造:节点的结构与节点等待机制.在结构上引入了 ...

  5. java 多线程缓存_[Java教程]【JAVA并发编程实战】12、使用condition实现多线程下的有界缓存先进先出队列...

    [Java教程][JAVA并发编程实战]12.使用condition实现多线程下的有界缓存先进先出队列 0 2016-11-29 17:00:10 package cn.study.concurren ...

  6. Java并发编程实战————恢复中断

    中断是一种协作机制,一个线程不能强制其他线程停止正在执行的操作而去执行其他操作. 什么是中断状态? 线程类有一个描述自身是否被中断了的boolean类型的状态,可以通过调用 .isInterrupte ...

  7. Java并发编程实战————Executor框架与任务执行

    引言 本篇博客介绍通过"执行任务"的机制来设计应用程序时需要掌握的一些知识.所有的内容均提炼自<Java并发编程实战>中第六章的内容. 大多数并发应用程序都是围绕&qu ...

  8. Java并发编程实战————Semaphore信号量的使用浅析

    引言 本篇博客讲解<Java并发编程实战>中的同步工具类:信号量 的使用和理解. 从概念.含义入手,突出重点,配以代码实例及讲解,并以生活中的案例做类比加强记忆. 什么是信号量 Java中 ...

  9. Java并发编程实战_不愧是领军人物!这种等级的“Java并发编程宝典”谁能撰写?...

    前言 大家都知道并发编程技术就是在同一个处理器上同时的去处理多个任务,充分的利用到处理器的每个核心,最大化的发挥处理器的峰值性能,这样就可以避免我们因为性能而产生的一些问题. 大厂的核心负载肯定是非常 ...

最新文章

  1. 推荐一个关于.NET平台数据结构和算法的好项目
  2. 微服务中为什么需要服务发现?
  3. 怎么给mysql用户添加权限_MySQL下添加用户以及给予权限的实现
  4. (1) nginx的安装
  5. 解决function id unknown issue
  6. oracle参数文件、控制文件、数据文件、日志文件的位置及查询方法
  7. Graph_Master(连通分量_Poj_1904)
  8. easyui layout 收缩的bug
  9. 谁“玩死了”共享单车?
  10. 给程序员的建议(转自李开复)
  11. 测试oracle的存储过程,测试技能:在oracle中自用存储过程进行测试数据构造
  12. 国密SM2算法的只求理解不求甚解 (5/5)SM2算法签名验签协议
  13. 顶级赛事!2021 CCF大数据与计算智能大赛强势来袭~
  14. Android Studio 开关控件Switch使用
  15. CAD给标注尺寸加上下公差的方法
  16. 成功男友因具备的品质
  17. 中文停用词表整理(1893个)
  18. Python3.6-Flask:制作一个语音对话问答机器人系统(网页版)
  19. 微信小程序约课_基于微信小程序的瑜伽馆约课系统设计
  20. 第三个 1024,三年的成长与期盼!

热门文章

  1. 论文浅尝|简单高效的知识图谱表示学习负样本采样方法
  2. 使用numpy实现神经网络模块
  3. ChineseDiachronicCorpus项目,大规模中文历时语料库
  4. 【秒懂】号称最为简明实用的Django上手教程
  5. 《C#与.net高级编程》——第一支柱:C#的封装
  6. abp radio表单元素 消失了
  7. Node.js对MongoDB进行增删改查操作
  8. 前端开发推荐-创建一个精美的jquery图片库效果
  9. Web在线操作Office之Word
  10. ASP。NET的设计思想