【多线程】可重入锁 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,是实现 ...
随机推荐
- java中如何获得src路径
代码 解析: 类名.class.get类加载器().getResourceAsStream("文件名"); 案例代码: Demo.class.getClassLoader().ge ...
- html5的video元素学习手札
为了监控移动端视频播放的情况,研究了一下 html5 <video> 标签的属性与事件触发,及其在各系统和各个浏览器的兼容情况 属性与事件 理解清楚属性和事件,才能更好的使用 video ...
- 关于websocket制作聊天室的的一些总结
websocket的总结 在一个聊天室系统中,常常使用websocket作为通信的主要方式.参考地址:https://www.jianshu.com/p/00e... 关于自己的看法:websocke ...
- javaweb之修改功能
数据库的修改功能,主要是通过查询,保留之前的数据,得到当前想要修改的页面,并进行修改. 一.dao层 在dao层需要添加两个fangfa,一个查询,一个修改(这是整个dao层,包括之前的增删.浏览) ...
- javaweb图书管理系统之不同用户跳转不同页面
关于分级自测题,我们知道该系统一共分为两个角色,一个是读者,一个是管理员,我们需要根据不同用户去到不同的页面,所以我们需要写一个登陆界面. 本文先写这个功能的实现,该功能主要在servlet里面实现. ...
- formData请求接口传递参数格式
element ui组件方法的传递 //引入 组件. <el-upload class="avatar-uploader" :action="action" ...
- 【.NET 6】使用EF Core 访问Oracle+Mysql+PostgreSQL并进行简单增改操作与性能比较
前言 唠嗑一下.都在说去O或者开源,但是对于数据库选型来说,很多人却存在着误区.例如,去O,狭义上讲,是去Oracle数据库.但是从广义上来说,是去Oracle公司产品或者具有漂亮国垄断地位和需要商 ...
- phpshe xml注入
*php商城系统 xml注入* **页面样式* *Xml原理参考:* https://www.cnblogs.com/20175211lyz/p/11413335.html *漏洞函数simplexm ...
- Python入门-面向对象三大特性-封装
一.封装 封装,顾名思义就是将内容封装到某个地方,以后再去调用被封装在某处的内容. 所以,在使用面向对象的封装特性时,需要: 将内容封装到某处 从某处调用被封装的内容 第一步:将内容封装到某处 sel ...
- LC-141andLC-142
142. 环形链表 II 思路: 设链表共有 a+b 个节点,其中 链表头部到链表入口 有 a 个节点(不计链表入口节点), 链表环 有 b 个节点. 再设两指针分别走了 f,s 步,则有: f = ...