深入学习锁--Lock各种使用方法

news2025/2/24 21:03:02

一、什么是Lock

Lock是一个接口,通常所说的可重入锁是指Lock的一个实现子类ReentrantLock

二、Lock实现步骤: 

①创建锁对象Lock lock = new ReentrantLock();

②加锁lock.lock();

③释放锁lock.unlock();

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
 
/**
 * 手动锁(可重入锁的基本使用)
 */
public class ThreadLock {
    public static void main(String[] args) {
        //1.创建锁对象
        Lock lock = new ReentrantLock();
        //2.加锁操作
        lock.lock();
        try{
            //业务代码(可能会非常复杂->可能会导致异常,后面的代码就不执行了,锁就无法释放,当前线程会永久占用锁资源)
            //所以要用try-catch-finally(可以没有catch)
            System.out.println("你好,ReentrantLock.");
        } finally {
            //3.释放锁(一定要放在finally中)
            lock.unlock(); 
        }
    }
}

--->注意事项:

1.unlock()一定要放在finally里,否则可能导致锁资源永久占用问题。

2.lock()要放到try外(官方建议)或try中的首行(问题不大)。

lock.lock();  
try {
    
} finally {
    lock.unlock()
}
try {
    lock.lock(); 
    int n = 1/0; 
} finally {
    lock.unlock()
}

--->这种不行

try {
    int n = 1/0;
    lock.lock();  
} finally {
    lock.unlock()
}

原因有两个:

  1. 如果放在 try ⾥⾯,因为 try 代码中的异常导致加锁失败,但还会执行 finally 释放锁的操作。 未加锁却释放锁,肯定会报错。
  2. 报错信息中:unlock 异常会覆盖 try ⾥⾯的业务异常,从而增加调式程序和修复程序的复杂度,增加排查错误的难度。

三、Lock指定锁类型——公平锁和非公平锁

//1.创建锁对象
Lock lock = new ReentrantLock(true); //公平锁
Lock lock = new ReentrantLock(); //非公平锁
Lock lock = new ReentrantLock(false); //非公平锁 

使用公平锁比使用非公平锁要慢!

四、(面试必问)

4.1synchronized VS Lock(ReentrantLock)

  1. 实现方式:Synchronized是Java语言内置的关键字,而Lock是一个Java接口。
  2. 锁的获取和释放:Synchronized是隐式获取和释放锁,由Java虚拟机自动完成;而Lock需要显式地调用lock()方法获取锁,并且必须在finally块中调用unlock()方法来释放锁。
  3. 可中断性:在获取锁的过程中,如果线程被中断,synchronized会抛出InterruptedException异常并且自动释放锁,而Lock则需要手动捕获InterruptedException异常并处理,同时也支持非阻塞、可轮询以及定时获取锁的方式。
  4. 公平性:Synchronized不保证线程获取锁的公平性,而Lock可以通过构造函数指定公平或非公平锁。
  5. 锁状态:Synchronized无法判断锁的状态,而Lock可以通过tryLock()、isLocked()来判断锁的状态(线程是否可能取到锁、锁是否被占用等)。
  6. 粒度:Synchronized锁的粒度较粗,只能锁住整个方法或代码块,而Lock可以细粒度地控制锁的范围,比如锁某个对象的部分属性。
  7. 场景:如果在简单的并发场景下,推荐使用Synchronized;而在需要更高级的锁控制时,可以考虑使用Lock。

一般情况建议使用Synchronized,在JDK1.5之前Lock优于Synchronized,但在JDK1.5之后对Synchronized进行了优化,后面在性能方面基本与Lock一样且使用简单(有作者说"Synchronized是亲生的,JDK还是会一直优化他不会让Lock优于它")。

4.2 Synchronized原理 

Synchronized是Java语言中最常用的同步机制之一,它可以确保多个线程访问共享资源时的互斥性和可见性。Synchronized关键字的原理如下:

  1. Synchronized使用了内置锁(也称为监视器锁)来实现同步。每个Java对象都有一个内置锁,当该对象作为锁被获取时,其他试图获取该锁的线程会被阻塞,直到该锁被释放。
  2. Synchronized的锁是与对象相关联的。当一个线程进入Synchronized代码块时,它必须先获取该对象的锁才能执行代码,否则就会被阻塞。当该线程退出Synchronized代码块时,它会自动释放该对象的锁。
  3. Synchronized具有可重入性。如果当前线程已经获得了某个对象的锁,那么它可以继续访问该对象的其他Synchronized代码块,而不会被自己持有的锁所阻塞。
  4. Synchronized还具有volatile变量的读写语义。在使用Synchronized关键字时,内存屏障会确保本地线程中修改过的变量值被刷新回主内存,从而保证了多个线程之间对变量修改的可见性。

Synchronized通过使用内置锁、与对象关联的锁、可重入性以及内存屏障等机制来实现线程的同步和锁的管理,以保证对共享资源的访问具有互斥性和可见性。

4.3 Lock原理

Lock是Java语言中的一种高级同步机制,它提供了比Synchronized更加灵活和可扩展的同步特性。Lock机制的原理如下:

  1. Lock使用了对象的锁来实现同步。每个Lock对象都有一个锁,当该锁被获取时,其他试图获取该锁的线程会被阻塞,直到该锁被释放。
  2. Lock的锁是与对象无关的。相比于Synchronized关键字,Lock提供了更加灵活的方式来控制锁的获取和释放。例如,它支持可中断的获取锁操作、超时获取锁操作等等。因此,在需要手动控制锁的获取和释放时,Lock是一个很好的选择。
  3. Lock还具有可重入性。如果当前线程已经获得了某个Lock对象的锁,那么它可以继续访问该对象的其他Lock代码块,而不会被自己持有的锁所阻塞。
  4. Lock使用了条件变量来实现线程的等待和通知。Condition接口提供了await()、signal()和signalAll()等方法,用于线程之间的等待和通知,从而避免了Object类中wait()和notify()方法可能出现的信号丢失问题。

Lock通过使用对象的锁、与对象无关的锁、可重入性以及条件变量等机制来实现线程的同步和锁的管理,以保证对共享资源的访问具有互斥性和可见性。与Synchronized关键字相比,Lock提供了更加灵活和可扩展的同步特性,但也需要更多的代码来控制锁的获取和释放。

4.4、Synchronized与Lock使用

Synchronized

public class Counter {
        private int count;

        public synchronized void increment() {
            count++;
        }
    }

Lock

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

public class Counter {
    private int count;
    private Lock lock = new ReentrantLock();

    public void increment() {
        lock.lock();
        try {
            count++;
        } finally {
            lock.unlock();
        }
    }
}

上述代码也是定义了一个计数器类Counter,但是使用的是Lock接口来实现线程同步。在这种情况下,需要先创建一个ReentrantLock对象,然后在需要同步的代码块中调用lock()方法获取锁,在finally块中调用unlock()方法释放锁。

总的来说,Synchronized更加简单易用,适合用于一些简单的并发场景;而Lock提供了更多的灵活性和可扩展性,适合用于一些复杂的并发场景。

4.5ReentrantLock为什么比Synchronized更灵活?

ReentrantLock比Synchronized更灵活主要因为它提供了以下功能:

  • 可以指定公平锁或非公平锁。
  • 支持获取锁的超时时间。
  • 支持可中断的获取锁操作。
  • 可以通过tryLock()方法尝试获取锁,如果锁已经被占用,则返回false。
  • 支持多个Condition对象,可以让线程在不同的条件下等待和唤醒。

4.6什么是锁自旋?

锁自旋是一种优化锁竞争的技术,它用于减少线程在获取锁时的等待时间。当一个线程请求获取某个对象的锁时,如果此时锁已经被其他线程占用,那么该线程会进入阻塞状态等待锁的释放。而使用锁自旋技术,线程在发现锁被其他线程占用时,并不会立即进入阻塞状态,而是执行一段循环代码(称为自旋),等待锁的持有者释放锁。

原文链接:https://zhuanlan.zhihu.com/p/622760822

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

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

相关文章

十年数据分析师告诉你,这款国产数据分析工具真的很好用!

今天早上上班的时候经过一同事,看见他正苦大仇深的做着数据分析报告,老李走上前一问才知道,他的EXCEL又双叒罢工了。   数据分析师的核心能力是思维,而次核心能力就是工具。如古人云打仗需要一把趁手的兵器。对于初入行业的数据分…

DBET-6X/200G24-8K4V直动式比例溢流阀放大器

DBETX-1X/50G24-8NZ4M、DBETX-1X/180G24-8NZ4M、DBETX-1X/250G24-8NZ4M、DBETX-1X/315G24-8NZ4M、DBETX-1X/80G24-8NZ4M、DBET-6X/200G24-8K4V直动式比例溢流阀,用来限制系统压力,通过电磁铁控制电流可调节压力,参考特性曲线即使出现电气故障…

一文回顾 Polkadot 跨链技术演进,了解 Polkadot 2.0 的未来

Polkadot 的起源、完善和上线过程经历了怎样的技术迭新与路线升级?深入把握 Polkadot 技术模型与生态合约才能让我们更好地深耕 Polkadot 生态。 11 月 25 日晚上,Substrate Saturday 第 19 期活动如期举行,Parity 工程师 Suvi Dong、Kaicha…

外包干了4年,技术退步明显...

先说情况,大专毕业,18年通过校招进入湖南某软件公司,干了接近4年的功能测试,今年年初,感觉自己不能够在这样下去了,长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试&#xf…

预付费用电管理系统在商场及宿舍的应用

安科瑞电气股份有限公司 上海嘉定 201801 【摘要】本文主要讨论了预付费用电管理系统软、硬件的构建方法,软件系统的各个模块设计,以及软、硬件设计过程中解决的主要问题。1联5系8电2话171微3信5同2号2 【关键词】预付费电能表硬件设计软件设计 引言 …

香港服务器时间不准,差8小时

解决方案1 1、timedatectl查看系统时间 2、查看系统时区 ls /usr/share/zoneinfo 3、删除当前系统所处时区 rm /etc/localtime 4、创建软链接,以替换当前的时区信息 ln -s /usr/share/zoneinfo/Universal /etc/localtime 解决方案2 手动设置硬件时钟 1、设置系…

Hadoop学习笔记(HDP)-Part.13 安装Ranger

目录 Part.01 关于HDP Part.02 核心组件原理 Part.03 资源规划 Part.04 基础环境配置 Part.05 Yum源配置 Part.06 安装OracleJDK Part.07 安装MySQL Part.08 部署Ambari集群 Part.09 安装OpenLDAP Part.10 创建集群 Part.11 安装Kerberos Part.12 安装HDFS Part.13 安装Ranger …

JSP控制项目启动后默认去访问指定的WebServlet 而不是index.jsp

我的 index.jsp 代码是这样 现在每次启动 访问的都是index.jsp 这也是它的默认配置 我这里写了一个 WebServlet 代码是这样 简单可以理解为 我们定义了WebServlet 访问路径为1cginServlet 其中在request作用域中 定义了一个userName值为 欢迎来到jsp世界 然后 跳转向 page.j…

Selenium自动化测试技巧还不知道吗?

1、前言 与以前瀑布式开发模式不同,现在软件测试人员具有使用自动化工具执行测试用例套件的优势,而以前,测试人员习惯于通过测试脚本执行来完成测试。 但自动化测试的目的不是完全摆脱手动测试,而是最大程度地减少手动运行的测试…

ROS话题通信基本操作(C++)

目录 一、发布 1、实现步骤 2、代码实例 二、接收 1、实现步骤 2、代码实例 三、配置运行 1、修改CMakeLists.txt 2、运行结果 一、发布 1、实现步骤 1.包含头文件 2.初始化 ROS 节点:命名(唯一) 3.实例化 ROS 句柄 4.实例化 发布者 对象 5.组织被发布的数据&#…

微信小程序云开发报错

微信小程序云开发报错 起因是云开发报了个错误: fail: Error: cloud.callFunction:fail Error: errCode: -501000 | errMsg: [100003] env not exists (f8c78dea-9f77-43cf-9e7f-88c85f2a0795) (callId: 1701747734223-0.895078767368265) (trace: 11:42:14 star…

基础课17——任务问答引擎

任务问答引擎在智能客服系统中负责多轮对话的对话流设计、意图的管理、任务流的执行等功能。能够高效地进行意图识别与任务解析,实现多轮对话的流程设计,并驱动多轮会话任务的高效完成。 1.定义 任务问答引擎负责多轮对话的对话流设计、意图的管理、任…

Shopee买家通系统全自动模拟真人下单更真实

Shopee买家通系统的强大功能在于它可以为用户提供全自动、高效的下单体验。通过设置关键词和产品编号,用户可以轻松实现对目标商品的准确定位。而整个下单流程一旦设定完毕,软件程序将以模拟真人的方式,执行一系列全自动化的操作,…

销售工作中如何满足客户的需求?

销售工作中如何满足客户的需求? 在销售工作中,如果想要满足客户需求,第一步是要搞清楚客户的需求是什么,不能仅仅听客户的表面需求,在表面需求下隐藏的潜在需求是什么,另外还有客户的核心需求是什么&#…

易点易动设备管理系统--提升设备保养效率的工具

设备保养是企业运营中至关重要的一环,为了帮助市场推广人员提升设备保养效率,易点易动设备管理系统应运而生。本文将详细介绍易点易动设备管理系统的功能和优势,以及如何借助该系统提高设备保养效率,提升企业运营效益。 易点易动设…

Windows文件后缀名批量修改方法教程

目录 文件后缀名批量修改方法教程 1、新建一个文件夹,把需要改后缀名的文件都移到里面。 2、从“查看”菜单中找到“文件扩展名”,点击前面的小方框勾选,查看文件的后缀名。 3、新建一个txt文本,然后在里面输入下图字符&#xf…

计算机视觉-01-基于SegNet和U-Net的遥感图像语义分割(包含代码和数据)

文章目录 0. 数据下载1、介绍1.1 任务介绍1.2 数据集介1.2.1 数据集介绍1.2.2 数据集处理步骤 1.3 数据处理1.4 卷积神经网络1.4.1 SegNet1.4.1.1 定义SegNet网络1.4.1.2 读入数据集1.4.1.3 定义训练过程1.4.1.4 预测遥感图像 1.4.2 U-Net网络1.4.2.1 定义U-Net网络1.4.2.2 读入…

全息图着色器插件:Hologram Shaders Pro for URP, HDRP Built-in

8个新的Unity全息图着色器,具有故障效果,扫描线,网格线,和更多其他效果!与所有渲染管线兼容。 软件包添加了一系列的全息图着色器到Unity。从基本的全息图与菲涅耳亮点,先进的全息图与两种故障效应,扫描线,文体点阵和网格线全息图! 特色全息效果 Basic-支持菲涅耳发光照…

计算机速成课Crash Course - 07. 中央处理器

今天开始计算机速成课Crash Course的系列讲解。 更多技术文章,全网首发公众号 “摸鱼IT” 锁定 -上午11点 - ,感谢大家关注、转发、点赞! 计算机速成课Crash Course - 07. 中央处理器 07. 中央处理器 提示下,这集可能是最难的一…

python之记录程序运行时长工具

python之记录程序运行时长工具 废话不多话,上代码 from datetime import datetime, timedelta import timestart_time datetime.now()while True:current_time datetime.now()elapsed_time current_time - start_timeformatted_time str(elapsed_time).split(…