JUC锁框架——重入锁ReentrantLock
2019独角兽企业重金招聘Python工程师标准>>>
重入锁(ReentrantLock)
ReentrantLock是一种可重入的互斥锁,并且加锁是一种显式操作,对逻辑控制的灵活性远远大于synchronized关键字。重入锁是可以完全替代synchronized。并且重入锁的性能是远高于synchronized的,但是jdk6.0开始,jdk对synchronized做了大量的优化,使得两者性能差距不大。另外,ReentrantLock可结合Condition、以及提供了中断响应、锁申请等待限时、公平锁等。
公平锁、非公平锁(ReentrantLock)
ReentrantLock分为“公平锁”和“非公平锁”。它们的区别体现在获取锁的机制上是否公平。在“公平锁”的机制下,线程依次排队获取锁;而“非公平锁”在锁是可获取状态时,不管自己是不是在队列的开头都会获取锁。
运行如下代码,对比公平锁和非公平锁的运行结果
public static void main(String[] args) throws InterruptedException {Lock noFairReentrantLock = new ReentrantLock();Lock fairReentrantLock = new ReentrantLock(true);Thread[] threads = new Thread[10];for(int i=0;i<10;i++){threads[i] = new Thread(()->{System.out.println(Thread.currentThread().getName()+" [start]");fairReentrantLock.lock();//也可以切换为非公平锁,观察运行结果try {System.out.println(Thread.currentThread().getName()+" [获得锁]");}finally {fairReentrantLock.unlock();}});}for(int i=0;i<5;i++){threads[i].start();}for(int i=0;i<5;i++){threads[i].join();}}}
重入锁的中断响应功能
对于synchronized块来说,要么获取到锁执行,要么持续等待。而重入锁的中断响应功能就合理地避免了这样的情况。比如,一个正在等待获取锁的线程被“告知”无须继续等待下去,就可以停止工作了。
下面我们看一个利用中断响应功能解决的一个死锁问题
public static void main(String[] args) throws InterruptedException {ReentrantLock lock1 = new ReentrantLock();ReentrantLock lock2 = new ReentrantLock();//线程t1和t2构成了死锁,此时我们可以中断的方式解决死锁问题Runnable runnable = ()->{try {if(Thread.currentThread().getName().equals("t1")){lock1.lockInterruptibly(); //在加锁的过程中仍然可以相应中断Thread.sleep(100);lock2.lockInterruptibly();}else{lock2.lockInterruptibly();Thread.sleep(100);lock1.lockInterruptibly();}} catch (InterruptedException e) {e.printStackTrace();}finally {if (lock1.isHeldByCurrentThread()) lock1.unlock();if (lock2.isHeldByCurrentThread()) lock2.unlock();}};Thread t1 = new Thread(runnable,"t1");Thread t2 = new Thread(runnable,"t2");t1.start();t2.start();Thread.sleep(1000);//以中断的方式解决死锁问题t2.interrupt();}
锁申请等待限时
可以使用 tryLock()或者tryLock(long timeout, TimeUtil unit) 方法进行一次限时的锁等待。
- tryLock(),线程尝试获取锁,如果获取到锁则继续执行,如果锁被其他线程持有,则立即返回false,也就是不会使当前线程等待,所以不会产生死锁。
- tryLock(long timeout, TimeUtil unit),表示在指定时长内获取到锁则继续执行,如果等待指定时长后还没有获取到锁则返回false。
public static void main(String[] args) throws InterruptedException {ReentrantLock lock = new ReentrantLock();Runnable runnable = ()->{try {if (lock.tryLock(1, TimeUnit.SECONDS)) { // 等待1秒Thread.sleep(2000);} else {System.err.println(Thread.currentThread().getName() + "获取锁失败!");}} catch (Exception e) {if (lock.isHeldByCurrentThread()) lock.unlock();}};Thread t1 = new Thread(runnable,"t1");Thread t2 = new Thread(runnable,"t2");t1.start();t2.start();}
ReentrantLock 配合 Condition 使用
配合关键字synchronized使用的方法如:await()、notify()、notifyAll(),同样配合ReentrantLock 使用的Conditon提供了以下方法:
public interface Condition {void await() throws InterruptedException; // 类似于Object.wait()void awaitUninterruptibly(); // 与await()相同,但不会再等待过程中响应中断long awaitNanos(long nanosTimeout) throws InterruptedException;boolean await(long time, TimeUnit unit) throws InterruptedException;boolean awaitUntil(Date deadline) throws InterruptedException;void signal(); // 类似于Obejct.notify()void signalAll();
}
ReentrantLock 配合 Condition的例子
public static void main(String[] args) throws InterruptedException {ReentrantLock lock = new ReentrantLock(true);Condition condition = lock.newCondition();Thread t = new Thread(()->{try {lock.lock();System.err.println(Thread.currentThread().getName() + "-线程开始等待...");condition.await();System.err.println(Thread.currentThread().getName() + "-线程继续进行了");} catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock();}}, "t1");t.start();Thread.sleep(1000);System.err.println("过了1秒后...");lock.lock();condition.signal(); // 调用该方法前需要获取到创建该对象的锁否则会产生java.lang.IllegalMonitorStateException异常lock.unlock();}
ReentrantLock函数列表
// 创建一个 ReentrantLock ,默认是“非公平锁”。
ReentrantLock()
// 创建策略是fair的 ReentrantLock。fair为true表示是公平锁,fair为false表示是非公平锁。
ReentrantLock(boolean fair)
// 查询当前线程保持此锁的次数。
int getHoldCount()
// 返回目前拥有此锁的线程,如果此锁不被任何线程拥有,则返回 null。
protected Thread getOwner()
// 返回一个 collection,它包含可能正等待获取此锁的线程。
protected Collection<Thread> getQueuedThreads()
// 返回正等待获取此锁的线程估计数。
int getQueueLength()
// 返回一个 collection,它包含可能正在等待与此锁相关给定条件的那些线程。
protected Collection<Thread> getWaitingThreads(Condition condition)
// 返回等待与此锁相关的给定条件的线程估计数。
int getWaitQueueLength(Condition condition)
// 查询给定线程是否正在等待获取此锁。
boolean hasQueuedThread(Thread thread)
// 查询是否有些线程正在等待获取此锁。
boolean hasQueuedThreads()
// 查询是否有些线程正在等待与此锁有关的给定条件。
boolean hasWaiters(Condition condition)
// 如果是“公平锁”返回true,否则返回false。
boolean isFair()
// 查询当前线程是否保持此锁。
boolean isHeldByCurrentThread()
// 查询此锁是否由任意线程保持。
boolean isLocked()
// 获取锁。
void lock()
// 如果当前线程未被中断,则获取锁。
void lockInterruptibly()
// 返回用来与此 Lock 实例一起使用的 Condition 实例。
Condition newCondition()
// 仅在调用时锁未被另一个线程保持的情况下,才获取该锁。
boolean tryLock()
// 如果锁在给定等待时间内没有被另一个线程保持,且当前线程未被中断,则获取该锁。
boolean tryLock(long timeout, TimeUnit unit)
// 试图释放此锁。
void unlock()
转载于:https://my.oschina.net/cqqcqqok/blog/1944196
JUC锁框架——重入锁ReentrantLock相关推荐
- 年轻人,看看 Redisson 分布式锁—可重入锁吧!太重要了
作者 | 李祥 责编 | 张文 来源 | 企鹅杏仁技术站(ID:xingren-tech) 引言 作为后端开发,对于所谓的线程安全.高并发等一系列名词肯定都不会陌生,相关的一些概念及技术框架是面 ...
- Juc07_乐观锁和悲观锁、公平锁和非公平锁、递归锁(可重入锁)、死锁及排查、自旋锁
文章目录 ①. 乐观锁和悲观锁 ②. 公平锁和非公平锁 ③. 可重入锁(又名递归锁) ④. 死锁及排查 ⑥. 自旋锁 ①. 乐观锁和悲观锁 ①. 悲观锁(synchronized关键字和Lock的实现 ...
- 年轻人,看看Redisson分布式锁—可重入锁吧!太重要了
1.引言 作为后端开发,对于所谓的线程安全.高并发等一系列名词肯定都不会陌生,相关的一些概念及技术框架是面试中的宠儿,也是工作中解决一些特定场景下的技术问题的银弹.今天我们就来聊聊这些银弹中的其中一枚 ...
- 谈谈java并发锁(重入锁、读写锁、公平锁)
目录 重入锁 简单重入锁 重入锁的等待通知(Condition) 多Condition 公平锁和非公平锁 读写锁ReentrantReadWriteLock 锁优化总结: 重入锁和读写锁,他们具有比s ...
- 可重入锁 不可重入锁_什么是可重入锁?
可重入锁 不可重入锁 在Java 5.0中,增加了一个新功能以增强内部锁定功能,称为可重入锁定. 在此之前,"同步"和"易失性"是实现并发的手段. public ...
- 测试Lock锁-可重入锁(Java)
测试Lock锁-可重入锁(Java) package src.thread;import java.util.concurrent.locks.ReentrantLock;public class T ...
- 可重入锁/不可重入锁,公平锁/非公平锁,乐观锁/悲观锁,独享锁/共享锁,偏向锁/轻量级锁/重量级锁,分段锁,自旋锁
在并发编程中,会涉及到各种各样的锁,这篇文章主要介绍各种锁的分类以及作用. 介绍的内容如下: 可重入锁/不可重入锁 公平锁/非公平锁 乐观锁/悲观锁 独享锁/共享锁 偏向锁/轻量级锁/重量级锁 分段锁 ...
- 第二季:5公平锁/非公平锁/可重入锁/递归锁/自旋锁谈谈你的理解?请手写一个自旋锁【Java面试题】
第二季:5值传递和引用传递[Java面试题] 前言 推荐 值传递 说明 题目 24 TransferValue醒脑小练习 第二季:5公平锁/非公平锁/可重入锁/递归锁/自旋锁谈谈你的理解?请手写一个自 ...
- RocketMQ的broker处理消息commit时,加锁应该使用自旋锁还是重入锁
讨论的主题 以下内容基于rocketmq4.7.1版本,并且集群模型采用的是DLedger 2主4从,主从节点在不同的机架上,所以关于其中提到的压测数据请勿直接套用自己的环境,仅供参考. rocket ...
- Java 可重入锁 不可重入锁
文章目录 Java 可重入锁 & 不可重入锁 概述 论证synchronized是可重入锁: 论证Lock是可重入锁: 自定义不可重入锁: Java 可重入锁 & 不可重入锁 概述 可 ...
最新文章
- 英雄传说服务器维护中,英雄传说:星之轨迹 正统《轨迹》手游无法连接服务器是什么原因...
- mongodb 安装启动
- 无向图强联通分量-洛谷 P2860 [USACO06JAN]冗余路径Redundant Paths
- 源码与tarball套件管理程序笔记摘录
- json格式的字符串序列化和反序列化的一些高级用法
- python3图片转代码_python3图片转换二进制存入mysql示例代码
- 轻松搞定 Nginx 配置代码的神器!
- QML笔记-键盘事件中同时响应onDigitXXPressed与onPressed
- idea java jni 调试_使用 IntelliJ IDEA 和 IntelliJ Clion 进行 JNI 开发
- NetCDF文件介绍
- 前端系列教程之JS(自认为有用代码)
- Ant Design Upload 文件上传功能
- 广州三本找Java实习经历
- 论文写作课程收获总结
- dede织梦网站源码安装教程
- No387FirstUniqueCharacterInAString
- Linux 两台主机之间建立信任关系方式及基本原理
- 年份必须是4位数 C语言,输入年份(四位数),判断是否是闰年 C语言编程
- pytorch转onnx踩坑日记
- 卓音工作室2022讨论班第五期——JavaScript基础
热门文章
- Linux系统磁盘分区、删除分区、格式化、挂载、卸载、开机自动挂载的方法总结...
- JavaScript必须了解的知识点总结【转】
- Linux部署之批量自动安装系统之测试篇
- 123 Python程序中的线程操作-协程
- 一本通1598【 例 2】最大连续和
- vue开发中v-for在Eslint的规则检查下出现:Elements in iteration expect to have 'v-bind:key' directives...
- 剑指offer【书】之简历抒写
- Python网络编程笔记二
- IFTT-意大利金融交易税
- Elasticsearch从0.90(0.90.x)到1.2(1.x)API的变化-二