【Java多线程】多线程同步——对“ReentrantLock”类的简单理解

使用ReentrantLock和Semaphore实现单任务执行多线程唤醒 在多线程环境中,我面临一个挑战:执行一段资源密集型的业务逻辑,该逻辑仅需要同步执行一次。为了高效地处理这种情形,我的策略是确保在众多线程中,仅有单一线程负责执行这项任务,而其他线程则在等待这一过程完成后直接退出,无需再次执行相同的业务代码。 阅读详情

写在前面: 这篇文章是java.util.concurrent(J.U.C)包中ReentrantLock锁(又叫重入锁)的学习笔记与总结。并不适合新手对于ReentrantLock的入门,所以:当你扫一下目录后并未发现自己熟悉的点,那么你应该放弃继续读本文;反之,你可以挑选你认为我写得好的点看看。希望你我都能共同进步!


在发生了多线程环境下各个线程的读写操作并不是安全的情形下,需要有解决线程安全的方案!可以看看前两篇文章:
【Java多线程】简单理解Java“多线程”机制
【Java多线程】多线程同步——对“synchronized”关键字的简单理解

Java 提供了两种锁机制来控制多个线程对共享资源的互斥访问:

  • 第一个是 JVM 实现的 synchronized(内部锁),
  • 而另一个是 JDK1.5 实现的 ReentrantLock(重入锁)。ReentrantLock 是 java.util.concurrent(J.U.C)包中的锁,名叫重入锁。

ReentrantLock类

先介绍一下ReentrantLock类的相关方法,如果你以前有了解过ReentrantLock类,现在绝对是你复习它、构建知识体系的好机会!😄😄

Lock接口的特性:

  1. 自JDK1.5开始,替换synchronized,更加智能化的实现锁。
  2. 而Lock在发生异常时,如果没有主动通过unLock()去释放锁,则很可能造成死锁现象,因此使1. ck时需要在finally 块中释放锁,也即需要手动释放锁;
  3. Lock 可以让等待锁的线程响应中断,而synchronized 却不行;
  4. 通过Lock 可以知道有没有成功获取锁,而synchronized 却无法办到。

juc.locks.Lock接口:

  1. void lock(); 获得这个锁,如果当前被另一个线程占用,则阻塞。

  2. void unlock(); 释放这个锁。

  3. void lockInterruptibly(); 在等待锁的过程中,可以响应中断。

  4. Condition newCondition();

  5. Boolean tryLock(); 如果一个线程迟迟得不到锁,那么它就会自动放弃对该锁的请求。

  6. Boolean tryLock(long time, TimtUnit unit); 在time时间后都没有得到锁,就放弃放弃对该锁的请求。

ReentrantLock类特性:

  1. 重入锁(Reentrant),拥有一个计数器(hold count)来跟踪对lock方法的嵌套调用。每调用一层嵌套,hold count加一,没出一层嵌套,hold count减一。
  2. 重入锁的另一个特性:一个锁可以被一个线程连续获取多次。注意,如果获取多次,也一定要释放多次。

juc.locks.ReentrantLock类:(JDK1.5)

  • public class ReentrantLock extends Object implements Lock,Serializable { }
  • 是Lock接口的实现类;直接继承Object类

构造方法:

  • ReentrantLock() 构造“重入锁”,保护临界区
  • ReentrantLock(boolean fair) 如果fair等于true,则构造一个采用公平策略的锁,但速度慢!

第一个juc. Lock程序

使用Lock接口实现卖火车票

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Main {
	public static void main(String[] args) {
		//创建Runnable接口实现类对象
		Tickets t = new Tickets();
		//创建3个Thread类对象,传递Runnable接口实现类
		Thread t0 = new Thread(t);
		Thread t1 = new Thread(t);
		Thread t2 = new Thread(t);

		t0.start();
		t1.start();
		t2.start();
	}
}

class Tickets implements Runnable{
	private int ticket = 100;//定义出售的票源
	private Lock lock = new ReentrantLock();//在类的成员位置,创建Lock接口的实现类对象
	
	public void run(){
		while(true){
		    lock.lock();//调用Lock接口方法lock获取锁
			if( ticket > 0){//对票数判断,大于0,可以出售,变量--操作
				try{
				   Thread.sleep(10);
				   System.out.println(Thread.currentThread().getName()+" 出售第 "+ticket--);
				}catch(Exception ex){
					
				}finally{
					lock.unlock();//释放锁,调用Lock接口方法unlock
				}
			}
		}
	}
}

重入锁的特性

ReentrantLock特性一览:

  1. 中断响应:方法void lockInterruptibly();实现。
  2. 锁申请等待限时:方法Boolean tryLock();和Boolean tryLock(long time, TimtUnit unit);实现。
  3. 公平锁:ReentrantLock类的构造方法实现。

参看:实战Java并发程序设计-葛一鸣P73

对比synchronized和ReentrantLock

两者都是可重入锁。

  1. “可重入锁”概念是:自己可以再次获取自己的内部锁。
  2. 比如一个线程获得了某个对象的锁,此时这个对象锁还没有释放,当其再次想要获取这个对象的锁的时候还是可以获取的,如果不可锁重入的话,就会造成死锁。
  3. 同一个线程每次获取锁,锁的计数器都自增1,所以要等到锁的计数器下降为0时才能释放锁。

synchronized 依赖于 JVM 而 ReentrantLock 依赖于 API

  • synchronized 是依赖于 JVM 实现的,前面我们也讲到了 虚拟机团队在 JDK1.6 为 synchronized 关键字进行了很多优化,但是这些优化都是在虚拟机层面实现的,并没有直接暴露给我们。
  • ReentrantLock 是 JDK 层面实现的(也就是 API 层面,需要 lock() 和 unlock() 方法配合 try/finally 语句块来完成),所以我们可以通过查看它的源代码,来看它是如何实现的。

ReentrantLock 比 synchronized 增加了一些高级功能
相比synchronized,ReentrantLock增加了一些高级功能。主要来说主要有三点:①等待可中断;②可实现公平锁;③可实现选择性通知(锁可以绑定多个条件)


java多线程——synchronized与ReentrantLock synchronized和ReentrantLock都是Java中用于实现线程同步的机制,它们之间存在一些显著的区别。 阅读详情

相关推荐

Java多线程并发的可重入锁ReentrantLock

可重入锁 Java中的可重入锁(ReentrantLock)是用于控制并发的一种工具,它的功能类似于Java内置的Synchronized语法。可重入锁是指一个线程可以多次对某个锁进行加锁操作,比如程序在多层调用中多次使用锁。而对于不可重入锁来说,进行两次以及上的加锁会导致死锁的产生。 ReentrantLock是一种独占锁,在独占模式下线程只能逐一使用锁,即任意时刻仅仅只能有一条线程持有锁。如下图,线程一首先成功调用lock方法进行加锁操作从而持有该锁,其它两个线程只能等待线程一释放锁。因为锁是可重入的,

seaboat——a free boat on the sea.(公众号:远洋号) 849

可重入锁与非可重入锁

锁的分类 什么是可重入锁 可重入锁又名递归锁,是指在同一个线程在外层方法获取锁的时候,再进入该线程的内层方法会自动获取锁(前提锁对象得是同一个对象或者class),不会因为之前已经获取过还没释放而阻塞。Java中ReentrantLock和synchronized都是可重入锁,可重入锁的一个优点是可一定程度避免死锁。 ReentrantLock和synchronized都是重入锁, 可重入锁的好处:【1.避免死锁】【2.提升封装性】 案例实现 电影院预定预定电影院座位 预定座位就是个很好的lock

浪人与酒 2001

Cadence Virtuoso ADE L保姆级教程:从DC到Noise,一次搞定6种仿真设置

本文提供Cadence Virtuoso ADE L的全面仿真教程,涵盖DC工作点分析、瞬态响应、AC特性、零极点分布和噪声性能等6种仿真设置。通过详细的步骤和实用技巧,帮助工程师高效完成从基础配置到高级后处理的完整工作流,显著提升IC设计效率。

weixin_26841743的博客 597

重入锁:ReentrantLock 详解

在JDK5.0版本之前,重入锁的性能远远好于synchronized关键字,JDK6.0版本之后synchronized得到了大量的优化,二者性能也部分伯仲,但是重入锁是可以完全替代synchronized关键字的。除此之外,重入锁又自带一系列高逼格UBFF:可中断响应、锁申请等待限时、公平锁。另外可以结合Condition来使用,使其更是逼格满满。先来盘花生米:package somhu;impo

Somhu的博客 3万+

初识机会网络仿真器ONE中ExternalMovement移动模型(导入外部移动数据)

最近半个月一直在研究ONE中关于ExternalMovement移动模型的源代码,在网上几乎没有找到相关的资料,很是苦恼,如果有共同研究方向的小伙伴欢迎联系我,共同讨论进步。 下面记录一下几点感悟: 1、使用外部数据的前提是在ONE的配置文件中增加及修改相关代码: Group.movementModel = ExternalMovement ExternalMovement.file = move...

qq_36974792的博客 657

【论文复现】自动化细胞核分割与特征分析

HoVer-Net是一种精心设计的多分支深度学习网络架构,专为处理复杂的多组织显微图像中的细胞核实例分割与精确分类任务而开发。该网络通过创新的策略,不仅有效解决了细胞核在密集聚集区域难以准确区分的问题,还实现了对每个独立细胞核类型的细致分类。此外,HoVer-Net还引入了专门的上采样分支,这一设计旨在对每个成功分割出的细胞核实例进行进一步的核类型分类。这一分支利用高级语义信息,结合精心设计的分类策略,能够准确判断每个细胞核的所属类型,为医学研究提供了宝贵的细胞水平信息。

2201_75366661的博客 1978

ReentrantLock 中的 4 个坑

JDK 1.5 之前 synchronized 的性能是比较低的,但在 JDK 1.5 中,官方推出一个重量级功能 Lock,一举改变了 Java 中锁的格局。JDK 1.5 之前当我们谈到锁时,只能使用内置锁 synchronized,但如今我们锁的实现又多了一种显式锁 Lock。 Lock 简介 Lock 是一个顶级接口,它的所有方法如下图所示: 它的子类列表如下: 我们通常会使用 ReentrantLock 来定义其实例,它们之间的关联如下图所示: PS:Sy..

欢迎来到我的博客 772

AI驱动的iOS逆向工程自动化:14阶段工作流与Ghidra集成实践

逆向工程是软件安全分析的核心技术,通过反汇编、调试等手段解析程序内部逻辑与数据流。其原理在于将编译后的二进制代码还原为可理解的逻辑结构,从而发现潜在漏洞或理解软件行为。在移动安全领域,iOS逆向工程具有重要技术价值,能够用于安全审计、漏洞挖掘与恶意软件分析。传统iOS逆向依赖ipsw、class-dump、Frida等工具链组合,存在学习曲线陡峭与流程碎片化问题。本文介绍的ios-reverse-skills项目创新性地将14阶段逆向工程方法论封装为AI可调用的标准化脚本集,通过Ghidra脚本实现Swif

weixin_27268733的博客 432

Java并发编程(三)--ReentrantLock

1.简介ReentrantLock是一个可重入(指持有锁的线程可以进行多次加锁、释放锁)的独占锁实现,拥有和synchronized一样的行为和语义,并且对其做了一些扩展,如记录持有者信息、Condition(以后的文章再讲)支持等等。 ReentrantLock基于AbstractQueuedSynchronizer实现了公平模式和不公平模式的独占锁。在构造方法中根据传入fair参数,设置syn

valleychen1111的博客 336

百度新闻评论内容抓取

通过抓包分析发现,百家号手机app端文章评论内容接口为:https://ext.baidu.com/api/comment/v1/comment/getlist?appid=101&sid=1008524_2-1010050_1-1007549_23033-1007550_23035&cuid=01B5EAF73E8A83BB842BE04E4FB6C656|23200201047...

codingforhaifeng的博客 2422

基于 Python 的 LIF 模型:探索神经元同步与小世界网络

首先,我们定义了一个LIFNeuronself.soma.L = self.soma.diam = 12.6157 # 固定神经元形状self.cm = cm # 电容self.V_rest = V_rest # 静息电位self.V = V_rest # 初始化膜电位在初始化过程中,每个神经元被赋予初始的静息电位,并且其膜电位会在后续的模拟过程中动态变化。

qq_36224726的博客 1423

深入理解Java中的多线程与同步

在计算机领域,多线程是指一个进程(程序的执行单元)中包含多个执行流。这意味着程序可以同时执行多个任务,提高了程序的并发性和响应性。Java通过java.lang.Thread类和java.util.concurrent包提供了丰富的多线程支持。

qq_28068311的博客 1289

51雾化器实现

1. 雾化器简介 雾化器是将试液雾化的一种器械。雾化器是原子化系统的重要部件,其性能对测定的精密度和化学干扰等产生显著影响。因此要求雾化器喷雾稳定、雾滴细小、均匀和雾化效率高。雾化器的类型有超声雾化器,空气压缩式雾化器,网式雾化器。超声雾化器因其价格合适,适合家用,被广泛应用于加湿器,香薰机等各种小家电,也在医疗领域有很多的应用。家用雾化器的主要器件是一枚雾化片。 家用雾化器分为两种不同类别雾化片,实孔雾化片和微孔雾化片,这两种的喷雾方法和工作原理是有所不同的。不同的雾化片需要特定的频率才能工作。 实孔雾

qq_42415953的博客 2万+

Java多线程详解(线程同步)

嗨喽~小伙伴们我来了, 上一章,我们通过三个例子(点击跳转)来介绍了线程安全问题,说到线程安全就不得不提到线程同步,它是解决线程安全的一种重要方法。本章就来简单的介绍一下何为线程同步。 从上一章的学习我们知道,当多个线程操作一个资源的时候,就有可能由于线程的不确定切换出现数据不一致的安全问题,那显然,我们要解决这个问题,就得想办法使得资源在某个时间戳只能被一个线程访问。基于这样的思想,我们提出了“队列与锁”的策略: 通俗理解,就是将所有线...

易果啥笔的博客 2855

微信H5网页支付JSAPI部分用户报错:system:access_denied 的解决方案

JSAPI 支付仅支持微信内置浏览器调用。

代码简单说 Vue、JAVA、PHP、Node.js 熟练运用,接口、架构、性能全搞定。 1685

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

【Java多线程】多线程同步——对“synchronized”关键字的简单理解

既然一个进程中可以有多个线程,并且多个线程共享资源,那么,由谁来管理这些个共享的资源,以至于不被各个线程争抢呢?

极客-多重人格递归 397

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

Java:Java学习笔记之ReentrantLock的简单理解和使用

ReentrantLock ReentrantLock1、相关知识1.1 公平锁和非公平锁1.2 可重入锁1.3、CAS算法2、背景、定义和特征2.1、背景2.2、定义2.3、特征3、基本结构4、基本使用4.1、解决背景问题4.2、重入锁 使用4.3、公平锁使用5、源码分析5.1、AQS5.2、非公平锁的实现原理5.2.1、lock方法获取锁:tryAcquire5.2.2、锁的释放:tryRelease5.3、公平锁的实现原理5.3.1、lock方法获取锁:tryAcquire5.3.2、锁的释放:try

JMW1407的博客 6990

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

Java 多线程同步机制深度解析:从 synchronized 到 ReentrantLock,带你吃透线程安全

本文深入解析了Java多线程编程中的两种核心同步机制:synchronized关键字和Lock接口。synchronized作为JVM原生支持的隐式锁,通过监视器锁实现互斥,具有自动释放、可重入等特性;而Lock接口的显式锁ReentrantLock则提供更灵活的锁控制,支持可中断、超时获取、公平锁等高级功能。文章从原理、用法、特性和性能四方面对比了两者的差异,并给出选型建议:简单场景优先使用synchronized,复杂同步需求考虑ReentrantLock。

qq_40303030的博客 1444

问:Java多线程同步&互斥→解析

Java提供多种线程同步和互斥机制,包括synchronized、ReentrantLock、ReadWriteLock等,每种机制各有优缺点。synchronized简单易用,ReentrantLock灵活复杂,ReadWriteLock提高并发读取。开发者应根据具体需求和场景选择合适的机制,确保线程安全和数据一致性。

技术铺掌柜 1652

Java多线程编程-(12)-Java中的队列同步器AQS和ReentrantLock锁原理简要分析

一、Lock接口在上一篇文章中: Java多线程编程-(5)-使用Lock对象实现同步以及线程间通信 介绍了如何使用Lock实现和synchronized关键字类似的同步功能,只是Lock在使用时需要显式地获取和释放锁,synchronized实现的隐式的获取所和释放锁。虽然Lock它缺少了(通过synchronized块或者方法所提供的)隐式获取释放锁的便捷性,但是却拥有了锁获取与释放的可操作性、

徐刘根的博客 4153

多线程的简单理解和使用

多线程的简单理解和使用 1,基础概念 1.1 进程和线程 根本区别: 进程:进程是操作系统资源分配的基本单位。 线程:线程是任务调度和执行的基本单位。 在开销方面: 进程:每个进程都有独立的代码和数据空间(程序上下文),程序之间的切换会有较大的开销。 线程:线程可以看做轻量级的进程,同一类线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器(PC),线程之间切换的开销小。 所处环境...

偏偏爱吃梨的博客 665

Semaphore与ReentrantLock——Java并发控制的利器

Java提供了多种锁机制,包含内置锁synchronized、显式锁Lock、以及其他的协作对象,如Semaphore、CountDownLatch、CyclicBarrier等。每种锁都有其特定的应用场景。

逆流的小鱼 1340

Java ReentrantLock

1. 锁的意义——线程同步 2. 案例——基于ReentrantLock来实现同步 public class A { public static ReentrantLock reentrantLock = new ReentrantLock(); public static void main(String[] args) { new Thread(() -> { testSync(); }, "t1").start()

weixin_35821291的博客 5102

多线程同步并发(synchronized和ReentrantLock)

简单来说,使用 Synchronized 关键字将一段代码逻辑,用一把锁给锁起来,只有获得了这把锁的线程才访问。并且同一时刻, 只有一个线程能持有这把锁, 这样就保证了同一时刻只有一个线程能执行被锁住的代码,从而确保代码的线程安全。例如,'+','-','='等这些算数运算符不具有原子性,会被别的进程打断。synchronized (counter.object){//加锁。//让数字线程等待 并释放锁。//同步锁 可以放在外面 也可以放在里面。//创建ReentrantLock锁对象。

m0_74776907的博客 887

java : 多线程保证操作同步ReentrantLock、synchronized

参考: Android 多线程保证操作同步(同步锁的俩种) 同步的方式 1.使用synchronized关键字。 使用synchronized关键字修饰的方法会同步执行,必须要等上一个synchronized执行完才会继续执行, 如果在执行过程中线程阻塞,他就会一直保持等待的状态,在这里不特别推荐使用这种方式, 如果你的需求是必须保证数据同步的情况下且保证不会出现其他情况使用户无法完成操作的情况...

火星男孩的分享空间 302

Java中如何有效避免多线程同步问题?

简单来说,多线程同步问题指的是当多个线程在没有正确同步机制的情况下,尝试访问和修改共享资源时,可能出现的数据不一致或不确定的行为。在设计线程模型时,我们需要考虑线程之间的协作关系、共享数据的访问方式以及潜在的同步问题。当一个线程进入同步方法或代码块时,它会获取一个监视器锁,其他试图进入同步方法或代码块的线程将被阻塞,直到锁被释放。然而,需要注意的是,原子变量并不能解决所有的同步问题。关键字提供了一种简单直观的同步方式,但过度使用可能会导致性能下降,因为每个被同步的代码块或方法在执行时都会阻塞其他线程。

ArcherMarjo的博客 1153
上一篇: 【JSP】第一个JSP程序:Hello,JSP
下一篇: 【Python功能体】语句写法:输入、输出、选择、循环
ALGO阿狗
博客等级 码龄9年 64粉丝 149原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值