当前位置: 首页 > news >正文

第 6 章 Java 并发包中锁原理剖析Part one

目录

6.1 LockSupport 工具类 

6.2 独占锁 ReentrantLock 的原理 

获取锁 

1.void lock() 方法

2.void lockInterruptibly() 方法

3.boolean tryLock() 方法

4.boolean tryLock(long timeout, TimeUnit unit) 方法

释放锁


6.1 LockSupport 工具类 

LockSupport 它的主要作用是 挂起和唤醒线程 ,该工具类是创建锁和其他同步类的基础。
LockSupport 类与每个使用它的线程都会关联一个许可证,在默认情况下调用 LockSupport 类的方法的线程是不持有许可证的。 LockSupport 是使用 Unsafe 类实现的。

6.2 独占锁 ReentrantLock 的原理 

ReentrantLock 可重入的独占锁,同时只能有一个线程可以获取该锁,其他获取该锁的线程会被阻塞而被放入该锁的 AQS 阻塞队列里面。

Sync 类直接继承自 AQS ,它的子类 NonfairSync FairSync 分别实现了获取锁的非公平与公平策略。默认情况下是非公平的实现。
public ReentrantLock() {sync = new NonfairSync();}public ReentrantLock(boolean fair) {sync = fair ? new FairSync() : new NonfairSync();}

获取锁 

1void lock() 方法

  • 当一个线程调用该方法时,说明该线程希望获取该锁。如果锁当前没有被其他线程占用并且当前线程之前没有获取过该锁,则当前线程会获取到该锁,然后设置当前锁的拥有者为当前线程,并设置 AQS 的状态值为 1【AQS state 状态值表示线程获取该锁的可重入次数】,然后直接返回。
  • 如果当前线程之前已经获取过该锁,则这次只是简单地把 AQS 的状态值加 1 后返回。
  • 如果该锁已经被其他线程持有, 则调用该方法的线程会被放入 AQS 队列后阻塞挂起。

2void lockInterruptibly() 方法

该方法与 lock() 方法类似,它的不同在于,它对中断进行响应,就是当前线程在调用该方法时,如果其他线程调用了当前线程的 interrupt ()方法,则当前线程会抛出 InterruptedException 异常,然后返回。
默 认 AQS 的状态值为 0 ,所以第一个调用 Lock 的 线程会通过 CAS 设置状态值为 1 CAS 成 功 则 表 示 当 前 线 程 获 取 到 了 锁, 然 后 setExclusiveOwnerThread 设置该锁持有者是当前线程。
如果这时候有其他线程调用 lock 方法企图获取该锁, CAS 会失败,然后会调用 AQS的 acquire 方法。注意,传递参数为 1

final void lock() {//(1)CAS设置状态值if (compareAndSetState(0, 1))setExclusiveOwnerThread(Thread.currentThread());else//(2)调用AQS的acquire方法acquire(1);
}

3boolean tryLock() 方法

尝试获取锁,如果当前该锁没有被其他线程持有,则当前线程获取该锁并返回 true , 否则返回 false 。注意,该方法不会引起当前线程阻塞。 ​​​​​​​ tryLock() 使用的是非公平策略。
public boolean tryLock() {
return sync.nonfairTryAcquire(1);
}
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}

4boolean tryLock(long timeout, TimeUnit unit) 方法

尝试获取锁,与 tryLock ()的不同之处在于,它设置了超时时间,如果超时时间没有获取到该锁则返回 false
public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {//调用AQS的tryAcquireNanos方法
return sync.tryAcquireNanos(1, unit.toNanos(timeout));}

释放锁

尝试释放锁,如果当前线程持有该锁,则调用该方法会让该线程对该线程持有的 AQS 状态值减 1,如果减去 1 后当前状态值为 0,则当前线程会释放该锁,否则仅仅减 1 而已。

如果当前线程没有持有该锁而调用了该方法则会抛出 IllegalMonitorStateException 异常 
public void lockInterruptibly() throws InterruptedException {sync.acquireInterruptibly(1);
}
public final void acquireInterruptibly(int arg)throws InterruptedException {//如果当前线程被中断,则直接抛出异常if (Thread.interrupted())throw new InterruptedException();//尝试获取资源if (!tryAcquire(arg))//调用AQS可被中断的方法doAcquireInterruptibly(arg);
}

http://www.lryc.cn/news/497803.html

相关文章:

  • 使用 Canvas 绘制一个镂空的圆形区域
  • 【Notepad++】---设置背景为护眼色(豆沙绿)最新最详细
  • 2024 数学建模国一经验分享
  • 安全见闻2
  • Web游戏开发指南:在 Phaser.js 中读取和管理游戏手柄输入
  • 代码随想录32 动态规划理论基础,509. 斐波那契数,70. 爬楼梯,746. 使用最小花费爬楼梯。
  • 记录一个Flutter 3.24单元测试点击事件bug
  • 使用Python将 word文档转pdf文档
  • 基于C#+SQLite开发数据库应用的示例
  • Vue基本语法
  • 芯片发展史
  • 我的知识图谱和Neo4j数据库的使用
  • ASP.NET CORE API 解决跨域问题
  • sram测试注意讨论
  • Mybatis 支持延迟加载的详细内容
  • word文档使用技巧笔记
  • 使用docker-compose部署搜索引擎ElasticSearch6.8.10
  • bugku-web-login2
  • 【 AI技术赋能有限元分析与材料科学应用实践】Neo-Hookean 材料与深度学习结合的有限元分析
  • StarRocks关于ConcurrentModificationException 问题的解决
  • 网络安全防护指南:筑牢网络安全防线(5/10)
  • 替代FTP最佳跨网文件传输解决方案——FileLink
  • Cesium在vue2中的引入和注意事项
  • CentOS 9 配置静态IP
  • 深入解析 Webhook:从原理到实践的全面指南
  • 基于springboot+vue实现的创新创业学分管理系统 (源码+L文+ppt)4-111
  • 如何高效地架构一个Java项目
  • Scala的模式匹配(8)
  • nodejs30: CSS 剪辑路径clip-path导致伪元素不可见问题及解决方法
  • Git分布式版本控制工具 Git基本概念、Git工作流程、Git常用命令、Git远程仓库、IDEA操作Git