Java 并发-Lock

news2024/12/23 1:58:26

目录

Lock

源码

lock()

tryLock()

tryLock(long time, TimeUnit unit)

Lock与synchronized


Lock

Lock 是 java.util.concurrent.locks包 下的接口。

上图是 java.util.concurrent.locks包下主要常用的类与接口的关系。

源码

public interface Lock {
    void lock();
    void lockInterruptibly() throws InterruptedException;  // 可以响应中断
    boolean tryLock();
    boolean tryLock(long time, TimeUnit unit) throws InterruptedException;  // 可以响应中断
    void unlock();
    Condition newCondition();
}

逐个分析Lock接口中每个方法。lock()、tryLock()、tryLock(long time, TimeUnit unit) lockInterruptibly()都是用来获取锁的。unLock()方法是用来释放锁的。newCondition() 返回 绑定到此 Lock 的新的 Condition 实例 ,用于线程间的协作。

  • lock()

在Lock中声明了四个方法来获取锁,那么这四个方法有何区别呢?首先,lock()方法是平常使用得最多的一个方法,就是用来获取锁。如果锁已被其他线程获取,则进行等待。如果采用Lock,必须主动去释放锁,并且在发生异常时,不会自动释放锁。因此,一般来说,使用Lock必须在try…catch…块中进行,并且将释放锁的操作放在finally块中进行,以保证锁一定被被释放,防止死锁的发生。通常使用Lock来进行同步的话,是以下面这种形式去使用的:

Lock lock = ...;
lock.lock();
try{
    //处理任务
}catch(Exception ex){

}finally{
    lock.unlock();   //释放锁
}
  • tryLock() 

tryLock()方法是有返回值的,它表示用来尝试获取锁,如果获取成功,则返回true;如果获取失败(即锁已被其他线程获取),则返回false,也就是说,这个方法无论如何都会立即返回(在拿不到锁时不会一直在那等待)。

Lock lock = ...;
if(lock.tryLock()) {
     try{
         //处理任务
     }catch(Exception ex){

     }finally{
         lock.unlock();   //释放锁
     } 
}else {
    //如果不能获取锁,则直接做其他事情
}
  • tryLock(long time, TimeUnit unit)

tryLock(long time, TimeUnit unit)方法和tryLock()方法是类似的,只不过区别在于这个方法在拿不到锁时会等待一定的时间,在时间期限之内如果还拿不到锁,就返回false,同时可以响应中断。如果一开始拿到锁或者在等待期间内拿到了锁,则返回true。

  • lockInterruptibly()

lockInterruptibly()方法比较特殊,当通过这个方法去获取锁时,如果线程 正在等待获取锁,则这个线程能够响应中断,即中断线程的等待状态。例如,当两个线程同时通过lock.lockInterruptibly()想获取某个锁时,假若此时线程A获取到了锁,而线程B只有在等待,那么对线程B调用threadB.interrupt()方法能够中断线程B的等待过程。

  由于lockInterruptibly()的声明中抛出了异常,所以lock.lockInterruptibly()必须放在try块中或者在调用lockInterruptibly()的方法外声明抛出 InterruptedException,但推荐使用后者,原因稍后阐述。因此,lockInterruptibly()一般的使用形式如下:

public void method() throws InterruptedException {
    lock.lockInterruptibly();
    try {  
     //.....
    }
    finally {
        lock.unlock();
    }  
}

注意,当一个线程获取了锁之后,是不会被interrupt()方法中断的。因为interrupt()方法只能中断阻塞过程中的线程而不能中断正在运行过程中的线程。因此,当通过lockInterruptibly()方法获取某个锁时,如果不能获取到,那么只有进行等待的情况下,才可以响应中断的。与 synchronized 相比,当一个线程处于等待某个锁的状态,是无法被中断的,只有一直等待下去。

最佳实践 (Best Practice):在使用Lock时,无论以哪种方式获取锁,习惯上最好一律将获取锁的代码放到 try…catch…,因为我们一般将锁的unlock操作放到finally子句中,如果线程没有获取到锁,在执行finally子句时,就会执行unlock操作,从而抛出 IllegalMonitorStateException,因为该线程并未获得到锁却执行了解锁操作。

Lock与synchronized

Lock 实现提供了比 synchronized 关键字 更灵活、更广泛、粒度更细 的锁操作,它能以更优雅的方式处理线程同步问题。也就是说,Lock提供了比synchronized更多的功能。但是要注意以下几点:

  1. synchronized是Java的关键字,因此是Java的内置特性,是基于JVM层面实现的,其经过编译之后,会在同步块的前后分别形成 monitorentermonitorexit 两个字节码指令;而Lock是一个Java接口,是基于JDK层面实现的,通过这个接口可以实现同步访问;
  2. 采用synchronized方式不需要用户去手动释放锁,当synchronized方法或者synchronized代码块执行完之后,系统会自动让线程释放对锁的占用;而 Lock则必须要用户去手动释放锁 (发生异常时,不会自动释放锁)如果没有主动释放锁,就有可能导致死锁现象。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1209388.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Flowable串行流程移动活动

在Activiti6和Activiti7中跳转节点都要自己实现,Flowable增加了这个功能。 一:简介 串行流程是指简单的一条线的流程,流程中如果包含会签、排它网关也算串行流程。 节点移动有三种方式: 向前移动foreward。向后移动back。直接跳…

并发编程产生的根本原因和C#怎么处理并发问题?

并发编程产生的根本原因和C#怎么处理并发问题? 前言 对于现在很多编程语言来说,多线程已经得到了很好的支持, 以至于我们写多线程程序简单,但是一旦遇到并发产生的问题就会各种尝试。 因为不是明白为什么会产生并发问题&#…

Android 布局优化,看过来 ~

屏幕刷新机制 基本概念 刷新率:屏幕每秒刷新的次数,单位是 Hz,例如 60Hz,刷新率取决于硬件的固定参数。帧率:GPU 在一秒内绘制操作的帧数,单位是 fps。Android 采用的是 60fps,即每秒 GPU 最多…

11-13 /11-14代理模式 AOP

调用者 代理对象 目标对象 代理对象除了可以完成核心任务,还可以增强其他任务,无感的增强 代理模式目的: 不改变目标对象的目标方法的前提,去增强目标方法 分为:静态代理,动态代理 静态代理 有对象->前提需要有一个类,那么我们可以事先写好一个类&a…

ATFX汇市:美国10月CPI数据来袭,通胀率料将进一步走低

ATFX汇市:本周二21:30,美国劳工部将公布10月未季调CPI年率,前值为3.7%,预期值3.3%;9月未季调核心CPI年率将于同一时间公布,前值为4.1%,预期值4.1%。机构预期美国名义通胀率将显著下降&#xff0…

【JVM】Java内存溢出分析(堆溢出、栈溢出、方法区溢出、直接内存溢出)

📫作者简介:小明java问道之路,2022年度博客之星全国TOP3,专注于后端、中间件、计算机底层、架构设计演进与稳定性建设优化,文章内容兼具广度、深度、大厂技术方案,对待技术喜欢推理加验证,就职于…

【极客时间-系列教程】Vim 实用技巧必知必会-更多常用命令:应对稍复杂的编辑任务

文章目录 更多常用命令:应对稍复杂的编辑任务光标移动文本修改文本对象选择 更多常用命令:应对稍复杂的编辑任务 几个基本的命令已经了解了,可以操作简单的任务,但一些很复杂的命令,并没有了解到,只知道几…

【C++】类和对象(4)--析构函数

一 概念 通过前面构造函数的学习,我们知道一个对象是怎么来的,那一个对象又是怎么没呢的? 析构函数:与构造函数功能相反,析构函数不是完成对对象本身的销毁,局部对象销毁工作是由编译器完成的。而对象在销…

发布自研大模型 夸克App将迎来全面升级

国产大模型阵营再添新锐选手。11月14日,阿里巴巴智能信息事业群发布全栈自研、千亿级参数的夸克大模型,将应用于通用搜索、医疗健康、教育学习、职场办公等众多场景。夸克App将借助自研大模型全面升级,加速迈向年轻人工作、学习、生活的AI助手…

Seatunnel单机和集群部署说明

编译 编译命令 mvn clean package -pl seatunnel-dist -am -Dmaven.test.skiptrue 部署 将seatunnel-dist\target目录下的apache-seatunnel-2.3.3-SNAPSHOT-bin.tar.gz上传至服务器 解压安装包到/opt/soft/seatunnel目录下 配置环境变量 export SEATUNNEL_HOME/opt/soft/s…

【MySQL】事务(下)

文章目录 1. 各个隔离级别的演示事务隔离级别 —— 读未提交事务隔离级别—— 读提交事务隔离级别 —— 可重复读事务隔离级别 —— 串行化脏读 不可重复读 幻读的理解 2. MVCC机制读写3个记录隐藏列字段undo日志模拟MVCCread view 理论 3. 读提交与 可重复读的区别两者本质区别…

分布式锁介绍

为什么需要分布式锁 在单机部署的系统中,使用线程锁来解决高并发的问题,多线程访问共享变量的问题达到数据一致性,如使用synchornized、ReentrantLock等。 但是在后端集群部署的系统中,程序在不同的JVM虚拟机中运行,且…

ISP 处理流程

#灵感# 摆烂时间太长了,感觉知识忘光光了。重新学习,常学常新。 因为公司文档都不让摘抄、截取,所以内容是工作的一些自己记录和网络内容,不对的欢迎批评指正。 1、ISP概述 ISP是Image Signal Processor 的简称,也就…

【计算机网络】VLAN原理和配置

目录 1、VLAN的原理 1.1、什么是VLAN 1.2、为什么要使用VLAN 1.3、VLAN的三种端口类型 1.4、VLAN的划分方法 2、VLAN的配置 1、VLAN的原理 1.1、什么是VLAN VLAN(Virtual Local Area Network)即虚拟局域网,是将一个物理的LAN在逻辑上…

key的性能保障,事件处理器,表单控件等介绍

4-2key设置-性能的保障 不能修改原数组的方法,如果想要修改原数组,就进行重新赋值 this.items this.items.filter((item) > item.message.match(/Foo/)) keyCode键的值**key设置-性能的保障**提高性能,可以对比老的虚拟dom,一样的就留着,不一样就补上Vue默认按照"就地…

2024年孝感初中级工程师职称评审要求

孝感工程类初级职称、中级职称职称评审相关要求,满足什么条件可以评审孝感职称呢?秋禾火告诉你 什么人可以在孝感申报职称 1.在孝感本地注册登记1年以上,按规定缴纳社保的的制造业、建筑业等生产类民营企业。2.参加评审的人员与所属企业签订…

使用CXF调用WSDL(二)

简介 本篇文章主要解决了上篇文章中遗留的对象嵌套问题,要想全面解析无限极的对象嵌套需要使用递归去解决 上文链接: 使用CXF调用WSDL(一) 上文回顾 上文使用了单方法“ call() ”解决了List和基本类型(含String&…

用户登录信息如何存放

放到ThreadLocal LoginUserInfoDto 缓存登录信息的实体,我这里只放了一个手机号就够了。可以根据自己的需要修改,比如角色权限等等 package com.fox.domain.dto;/*** author * 当前登录人信息*/ public class LoginUserInfoDto {/*** 当前登录人 手机号…

什么是变更管理?对IT管理有什么帮助?

变更管理是指在最短的中断时间内完成基础架构,或服务的任一方面的变更而对其进行控制的服务管理流程。变更管理的目标是确保在变更实施过程中使用标准的方法和步骤,尽快地实施变更,以便最小化由变更所导致的业务中断,将变更对业务的影响减小到…

使用Tauri开发桌面应用

本文是对视频 Tauri入门教程[1]的学习与记录 Tauri官网[2] 对 node版本有要求 创建项目及目录介绍: 项目的目录结构如下 可以安装推荐的插件 执行npm run tauri build出错,根据 https://github.com/tauri-apps/tauri/issues/7430 执行 yarn add -D tauri-apps/cli && y…