【多线程】可重入锁 ReentrantLock
java除了使用关键字synchronized外,还可以使用ReentrantLock实现独占锁的功能。而且ReentrantLock相比synchronized而言功能更加丰富,使用起来更为灵活,也更适合复杂的并发场景。
一、简介
ReentrantLock常常对比着synchronized来分析,我们先对比着来看然后再一点一点分析。
- synchronized是独占锁,加锁和解锁的过程自动进行,易于操作,但不够灵活。ReentrantLock也是独占锁,加锁和解锁的过程需要手动进行,不易操作,但非常灵活。
- synchronized可重入,因为加锁和解锁自动进行,不必担心最后是否释放锁;ReentrantLock也可重入,但加锁和解锁需要手动进行,且次数需一样,否则其他线程无法获得锁。
- synchronized不可响应中断,一个线程获取不到锁就一直等着;ReentrantLock可以响应中断。
ReentrantLock好像比synchronized关键字没好太多,我们再去看看synchronized所没有的,一个最主要的就是ReentrantLock还可以实现公平锁机制。什么叫公平锁呢?也就是在锁上等待时间最长的线程将获得锁的使用权。通俗的理解就是谁排队时间最长谁先执行获取锁。
二、使用
1、简单使用
代码:
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @description 可重入锁测试
* @author hzx
* @date 2022-04-01
*/
public class ReentrantLockTest {
private static final Lock lock = new ReentrantLock();
public static void main(String[] args) {
new Thread(() -> test(),"线程A").start();
new Thread(() -> test(),"线程B").start();
}
public static void test() {
try {
lock.lock();
System.out.println(Thread.currentThread().getName()+"获取了锁");
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(Thread.currentThread().getName()+"释放了锁");
lock.unlock();
}
}
}
执行结果:
线程A获取了锁
线程A释放了锁
线程B获取了锁
线程B释放了锁
在这里我们定义了一个ReentrantLock,然后再test方法中分别lock和unlock,运行一边就可以实现我们的功能。这就是最简单的功能实现,代码很简单。我们再看看ReentrantLock和synchronized不一样的地方,那就是公平锁的实现。
2、公平锁实现
首先new一个ReentrantLock的时候参数为true,表明实现公平锁机制。公平锁的含义就是谁等的时间最长,谁就先获取锁。在这里我们多定义几个线程,然后在test方法中循环执行了两次加锁和解锁的过程。
代码:
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @description 可重入锁测试(公平锁实现)
* @author hzx
* @date 2022-04-01
*/
public class ReentrantLockTest2 {
private static final Lock lock = new ReentrantLock(true);
public static void main(String[] args) {
new Thread(() -> test(),"线程1").start();
new Thread(() -> test(),"线程2").start();
new Thread(() -> test(),"线程3").start();
new Thread(() -> test(),"线程4").start();
new Thread(() -> test(),"线程5").start();
}
public static void test() {
for (int i = 0; i < 2; i++) {
try {
lock.lock();
System.out.println(Thread.currentThread().getName()+"获取了锁");
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
}
执行结果:
线程1获取了锁
线程2获取了锁
线程3获取了锁
线程4获取了锁
线程5获取了锁
线程1获取了锁
线程2获取了锁
线程3获取了锁
线程4获取了锁
线程5获取了锁
3、非公平锁实现
非公平锁那就随机的获取,谁运气好,cpu时间片轮到哪个线程,哪个线程就能获取锁,和上面公平锁的区别很简单,就在于先new一个ReentrantLock的时候参数为false,当然我们也可以不写,默认就是false。
代码:
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @description 可重入锁测试(非公平锁实现)
* @author hzx
* @date 2022-04-01
*/
public class ReentrantLockTest3 {
private static final Lock lock = new ReentrantLock(false);
public static void main(String[] args) {
new Thread(() -> test(),"线程1").start();
new Thread(() -> test(),"线程2").start();
new Thread(() -> test(),"线程3").start();
new Thread(() -> test(),"线程4").start();
new Thread(() -> test(),"线程5").start();
}
public static void test() {
for (int i = 0; i < 2; i++) {
try {
lock.lock();
System.out.println(Thread.currentThread().getName()+"获取了锁");
TimeUnit.MILLISECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
}
执行结果:
线程1获取了锁
线程2获取了锁
线程2获取了锁
线程3获取了锁
线程1获取了锁
线程3获取了锁
线程4获取了锁
线程4获取了锁
线程5获取了锁
线程5获取了锁
整个过程是随机的,没有固定的先后顺序,亲自测试时可以将for循环的次数增大,可以明显看出效果。
【多线程】可重入锁 ReentrantLock的更多相关文章
- Java多线程——深入重入锁ReentrantLock
简述 ReentrantLock 是一个可重入的互斥(/独占)锁,又称为“独占锁”. ReentrantLock通过自定义队列同步器(AQS-AbstractQueuedSychronized,是实现 ...
- synchronized关键字,Lock接口以及可重入锁ReentrantLock
多线程环境下,必须考虑线程同步的问题,这是因为多个线程同时访问变量或者资源时会有线程争用,比如A线程读取了一个变量,B线程也读取了这个变量,然后他们同时对这个变量做了修改,写回到内存中,由于是同时做修 ...
- Java 重入锁 ReentrantLock 原理分析
1.简介 可重入锁ReentrantLock自 JDK 1.5 被引入,功能上与synchronized关键字类似.所谓的可重入是指,线程可对同一把锁进行重复加锁,而不会被阻塞住,这样可避免死锁的产生 ...
- 轻松学习java可重入锁(ReentrantLock)的实现原理
转载自https://blog.csdn.net/yanyan19880509/article/details/52345422,(做了一些补充) 前言 相信学过java的人都知道 synchroni ...
- java 可重入锁ReentrantLock的介绍
一个小例子帮助理解(我们常用的synchronized也是可重入锁) 话说从前有一个村子,在这个村子中有一口水井,家家户户都需要到这口井里打水喝.由于井水有限,大家只能依次打水.为了实现家家有水喝,户 ...
- 轻松学习java可重入锁(ReentrantLock)的实现原理(转 图解)
前言 相信学过java的人都知道 synchronized 这个关键词,也知道它用于控制多线程对并发资源的安全访问,兴许,你还用过Lock相关的功能,但你可能从来没有想过java中的锁底层的机制是怎么 ...
- 17_重入锁ReentrantLock
[概述] 重入锁可以完全代替synchronized关键字. 与synchronized相比,重入锁ReentrantLock有着显示的操作过程,即开发人员必须手动指定何时加锁,何时释放锁,所以重入锁 ...
- Java 显示锁 之 重入锁 ReentrantLock(七)
ReentrantLock 重入锁简介 重入锁 ReentrantLock,顾名思义,就是支持同一个线程对资源的重复加锁.另外,该锁还支持获取锁时的公平与非公平性的选择. 重入锁 ReentrantL ...
- 多线程通信的两种方式? (可重入锁ReentrantLock和Object)
(一)Java中线程协作的最常见的两种方式: (1)利用Object的wait().notify()和notifyAll()方法及synchronized (2)使用Condition.Reentra ...
- Java多线程系列——深入重入锁ReentrantLock
简述 ReentrantLock 是一个可重入的互斥(/独占)锁,又称为“独占锁”. ReentrantLock通过自定义队列同步器(AQS-AbstractQueuedSychronized,是实现 ...
随机推荐
- 关于CPU、指令集、架构、芯片的一些科普
作者:王强链接:https://zhuanlan.zhihu.com/p/19893066来源:知乎 随着智能设备的广泛普及,这几年媒体上越来越多的出现关于"架构""AR ...
- Javascript--function的name属性
1.非标准的name属性 function sayHi(){ console.log("Hi");} console.log(sayHi.name);
- canvas菜鸟基于小程序实现图案在线定制功能
前言 最近收到一个这样的需求,要求做一个基于 vue 和 element-ui 的通用后台框架页,具体要求如下: 要求通用性高,需要在后期四十多个子项目中使用,所以大部分地方都做成可配置的. 要求做成 ...
- vue和mint-ui loadMore 实现上拉加载和下拉刷新
首先安装mint-ui组件库 npm install mint-ui 在main.js中引入mint-ui和样式 import 'mint-ui/lib/style.css' import MintU ...
- TypeScript中变量调用时后缀感叹号和问号的区别
typescript编译时,当我们开启严格模式时,下面的代码就会报错: function doSomething(x: string | null) { console.log("Hello ...
- EMS批量为用户分配邮箱
组织单位"Office"下有10个域用户,可以通过PowerShell命令一次为该组织单位中的没有分配邮箱的域用户分配邮箱. 以Exchange管理员身份打开EMS控制台.在Pow ...
- SSM实现个人博客-day04
项目源码免费下载:SSM实现个人博客 有问题询问vx:kht808 3.项目搭建(SSM整合) (1)创建maven工程,导入相应的依赖 <properties> <project. ...
- Python-初见
目录 概述 关键字 标准数据类型 Number String List Tuple Set Dictionary 删除对象 数据类型转换 推导式 运算符 迭代器与生成器 迭代器 生成器 函数 参数传递 ...
- Python BeautifulSoup4 爬虫基础、多线程学习
针对 崔庆才老师 的 https://ssr1.scrape.center 的爬虫基础练习.Threading多线程库.Time库.json库.BeautifulSoup4 爬虫库.py基本语法
- windows10家庭版启用组策略gpedit.msc
启用组策略gpedit.msc 家庭版很多功能不能使用,凑巧用的就是家庭版. 还想使用gpedit.msc来关闭windows10的更新. 找到一个可行的方法. 需要创建一个脚本. 如果你没有编辑器, ...