聊聊java的两种锁同步锁和重入锁

java重入锁和同步锁有什么区别

在Java中,重入锁(ReentrantLock)和同步锁(Synchronized)都是用于实现线程同步的机制,但它们有一些区别。

  1. 可重入性:
    • 重入锁是可重入的,也就是说,同一个线程可以多次获取同一个重入锁而不会产生死锁。在获取锁之后,线程可以多次进入被保护的代码块,并且每次退出代码块时都要释放锁。
    • 同步锁也是可重入的。当一个线程获取到同步锁后,可以再次获取同一个锁而不会产生死锁。同步锁的可重入性是由Java虚拟机自动实现的。
  1. 锁的获取方式:
    • 重入锁需要手动获取和释放,即通过调用lock()方法获取锁,然后在合适的时候调用unlock()方法释放锁。
    • 同步锁是隐式获取和释放的,当线程进入同步代码块时,会自动获取同步锁;当线程退出同步代码块时,会自动释放同步锁。
  1. 粒度:
    • 重入锁提供了更细粒度的控制。可以通过使用tryLock()方法尝试获取锁、使用lockInterruptibly()方法支持可中断的获取锁等。
    • 同步锁相对来说粒度较大,只能使用synchronized关键字来修饰代码块或方法。
  1. 灵活性:
    • 重入锁提供了一些高级功能,如公平性设置、条件变量等,可以更灵活地控制线程的访问顺序和条件等待。
    • 同步锁相对简单,没有提供类似的高级功能。

什么场景用重入锁好

重入锁(ReentrantLock)在以下场景中通常比同步锁(Synchronized)更适用:

  1. 公平性要求:重入锁可以通过构造函数的参数设置为公平锁,从而按照线程请求锁的顺序来获取锁。而同步锁无法直接实现公平性,它总是采用非公平的方式获取锁。
  2. 可中断性要求:重入锁提供了lockInterruptibly()方法,可以在获取锁的过程中响应中断请求。而同步锁在获取锁的过程中无法响应中断请求,只能等待获取锁。
  3. 尝试获取锁:重入锁提供了tryLock()方法,可以尝试获取锁而不会发生阻塞。该方法可以用于实现一些特殊的业务逻辑,例如尝试获取锁一段时间后放弃。
  4. 多个条件变量:重入锁可以使用newCondition()方法创建多个条件变量,可以更灵活地实现线程之间的通信和协作。同步锁只能使用wait()notify()方法进行线程的等待和唤醒。

总的来说,如果需要更高级的功能、更细粒度的控制、公平性要求或可中断性要求,重入锁是一个更好的选择。但在一些简单的同步场景中,同步锁通常更加方便和易用。

重入锁如何锁类

重入锁(ReentrantLock)提供了一个条件变量(Condition)机制,可以用于线程之间的通信和协作。下面是一个示例:

ReentrantLock lock = new ReentrantLock();
Condition condition = lock.newCondition();new Thread(()->{
// 线程1lock.lock();try {System.out.println("1");// 执行一些操作while (true) {System.out.println("1 s");condition.await(); // 等待条件变量System.out.println("1 e");}// 执行其他操作} catch (InterruptedException e) {System.out.println("1 InterruptedException");throw new RuntimeException(e);} finally {lock.unlock();System.out.println("1 end");}}).start();Thread.sleep(1000);new Thread(()->{
// 线程2lock.lock();try {System.out.println("2");// 执行一些操作condition.signal(); // 唤醒线程1System.out.println("2 end");} finally {lock.unlock();}}).start();Thread.currentThread().join();

在上述示例中,我们创建了一个ReentrantLock对象lock和一个条件变量condition。在线程1中,我们获取锁并执行一些操作,然后在满足某个条件时,调用await()方法等待条件变量。在线程2中,我们获取锁并执行一些操作,然后设置条件变量并调用signal()方法唤醒线程1。

这样就可以使用条件变量来实现线程之间的通信和协作。需要注意的是,在使用条件变量时,需要先获取锁并在try-finally块中释放锁,以确保在任何情况下都能正确释放锁。

此外,需要注意的是,在等待条件变量时,应该总是使用while循环来检查条件是否满足,而不是使用if语句。这是因为,在多线程环境中,可能会出现虚假唤醒的情况,即线程在没有收到信号的情况下被唤醒。使用while循环可以避免这种情况。

同步锁如何锁类

在Java中,可以使用synchronized关键字来锁住类。具体来说,可以在静态方法或静态代码块中使用synchronized关键字来锁住类。下面是一个示例:

public class MyClass {// 静态变量private static int count = 0;// 静态方法public static synchronized void increment() {count++;}// 静态代码块static {synchronized(MyClass.class) {// 执行需要同步的代码块// ...}}
}

在上述示例中,我们定义了一个类MyClass,其中包含一个静态变量count和一个静态方法increment()。在increment()方法中,我们使用synchronized关键字来锁住该方法,以确保在同一时刻只有一个线程可以访问该方法。

另外,在静态代码块中,我们使用synchronized关键字来锁住类对象MyClass.class,以确保在同一时刻只有一个线程可以执行静态代码块中的代码。

这样就可以使用synchronized关键字来锁住类,确保在同一时刻只有一个线程可以访问被保护的代码块。需要注意的是,在实际使用中,需要谨慎使用类锁,以避免死锁或性能问题等,当然也可以锁住某个对象。

    public static void main(String[] args) {Map<String, String> list = new HashMap<String, String>();for (int i = 0; i < 5; i++) {String str = new String("hello" + i);if (list.containsKey(str)) {System.out.println(str+"存在");} else {String clock = new String("123");list.put(str, clock);}}System.out.println(Json.getJsonFromObject(list));ExecutorService executorService = Executors.newFixedThreadPool(3);for (int i = 0; i < 5; i++) {String str = new String("hello" + i);executorService.execute(() -> {String s = list.get(str);System.out.println(s + "========" + str);synchronized (s) {System.out.println(str + "获得锁");try {Thread.sleep(10000);} catch (InterruptedException e) {e.printStackTrace();}}System.out.println(str + "释放锁");});}System.out.println();}

在如上的代码示例中,你可以看到使用同步锁来锁住某个固定的对象,以达到细粒度锁的功能。

最后

总体来说,重入锁相对于同步锁提供了更多的灵活性和控制能力,但使用起来也更加复杂。在大部分情况下,使用同步锁已经足够满足线程同步的需求。只有在需要更高级的功能或更细粒度控制时,才需要考虑使用重入锁。

点赞关注评论一键三连,每周分享技术干货、开源项目、实战经验、国外优质文章翻译等,您的关注将是我的更新动力!

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

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

相关文章

Windows系统上如何搭建Linux操作系统

一、准备工作 1&#xff0c;VMware安装包 2&#xff0c;Centos IOS镜像 3&#xff0c;finalshell安装包 阿里云盘下载地址&#xff1a; https://www.alipan.com/s/uSQsWn15E3W 二&#xff0c;VMware安装 1&#xff0c;新建虚拟机 2&#xff0c;选择下一步 3&#xff0c;…

如何在Linux上部署1Panel运维管理面板并远程访问内网Web端管理界面

文章目录 前言1. Linux 安装1Panel2. 安装cpolar内网穿透3. 配置1Panel公网访问地址4. 公网远程访问1Panel管理界面5. 固定1Panel公网地址 前言 1Panel 是一个现代化、开源的 Linux 服务器运维管理面板。高效管理,通过 Web 端轻松管理 Linux 服务器&#xff0c;包括主机监控、…

Course1-Week3-分类问题

Course1-Week3-分类问题 文章目录 Course1-Week3-分类问题1. 逻辑回归1.1 线性回归不适用于分类问题1.2 逻辑回归模型1.3 决策边界 2. 逻辑回归的代价函数3. 实现梯度下降4. 过拟合与正则化4.1 线性回归和逻辑回归中的过拟合4.2 解决过拟合的三种方法4.3 正则化4.4 用于线性回归…

揭秘:微信淘宝客自动查券找券返利机器人的工作原理与实现思路

揭秘&#xff1a;微信淘宝客自动查券找券返利机器人的工作原理与实现思路 分享一篇文章&#xff0c;让我们一同探索微信淘宝客自动查券找券返利机器人的工作原理与实现思路。结合微赚淘客系统&#xff0c;我们将为你揭开这个智能购物助手的神秘面纱。 一、引言 随着人工智能…

elk(filebeat)日志收集工具

elk&#xff08;filebeat&#xff09;日志收集工具 elk&#xff1a;filebeat日志收集工具 和logstash相同 filebeat是一个轻量级的日志收集工具&#xff0c;所使用的系统资源比logstash部署和启动时使用的资源要小得多 filebeat可以运行在非Java环境。他可以代理logstash在…

彻底解决module java.base does not “opens java.io“

需求背景 最近在使用android studio导入hbuilder的HBuilder-Integrate-AS工程时候报错&#xff0c;错误消息如下两种。 错误描述 第一种 Failed to notify dependency resolution listener. void org.gradle.api.artifacts.DependencySubstitutions$Substitution.with(org.g…

mysql8报sql_mode=only_full_group_by(存储过程一直报)

1&#xff1a;修改数据库配置(重启失效) select global.sql_mode;会打印如下信息 ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION里面包含 ONLY_FULL_GROUP_BY&#xff0c;那么就重新设置&#xff0c;在数据库中输入以下代码&#xff0c;去掉ONLY_FULL_GROU…

UnityShader自定义cginc文件

1.概述 在使用UnityShader开发中&#xff0c;经常需要引入cginc文件&#xff0c;比如UnityCG.cginc。这些文件声明了很多内置的辅助函数和数据结构体&#xff0c;可避免大量重复编码工作。那么在实际开发中其实也需要把一些函数给封装起来&#xff0c;方便调用&#xff0c;那么…

【运维面试100问】(七)ceph基础题面试

本站以分享各种运维经验和运维所需要的技能为主 《python零基础入门》&#xff1a;python零基础入门学习 《python运维脚本》&#xff1a; python运维脚本实践 《shell》&#xff1a;shell学习 《terraform》持续更新中&#xff1a;terraform_Aws学习零基础入门到最佳实战 《k8…

linux下Kafka安装及基本操作

1.下载Kafka http://archive.apache.org/dist/kafka/1.1.0/ 2.解压并重命名 mkdir /usr/local/kafka cd /usr/local tar zxvf kafka_2.12-1.1.0.tgz mv kafka_2.12-1.1.0 ./kafka //把kafka_2.12-1.1.0下的文件拷贝到/usr/local/kafka下面3.配置kafka mkdir /usr/local/kaf…

加密系统,您的数据安全守护者,助您远离泄露风险!

随着云计算、大数据等技术的快速发展&#xff0c;企业在技术升级&#xff0c;业务上云的同时&#xff0c;也面临着来自互联网的各类安全威胁&#xff0c;并且导致数据信息的泄露。企业数据安全问题几乎为新时代人的焦虑又添上了一把火&#xff0c;面对形形色色的网络攻击手段&a…

Python版本与opencv版本的对应关系

python版本要和opencv版本相对应&#xff0c;否则安装的时候会报错。 可以到Links for opencv-python上面查看python版本和opencv版本的对应关系&#xff0c;如图&#xff0c;红框内是python版本&#xff0c;绿框内是opencv版本。 查看自己的python版本后&#xff0c;使用下面…

Linux AMH服务器管理面板本地安装与远程访问

最近&#xff0c;我发现了一个超级强大的人工智能学习网站。它以通俗易懂的方式呈现复杂的概念&#xff0c;而且内容风趣幽默。我觉得它对大家可能会有所帮助&#xff0c;所以我在此分享。点击这里跳转到网站。 文章目录 1. Linux 安装AMH 面板2. 本地访问AMH 面板3. Linux安装…

利用simlink转化HDL-verilog

首先在simlink中找到HDL CODER 打开红色Blank DUT&#xff0c;进入里面绿色的子系统开始设计系统 例如设计一个正弦信号发生器&#xff0c;里面用到了add、memory、relation operator、switch、constant、cos模块&#xff0c;cos模块选择了cordic算法&#xff0c;使用cordic那…

8.2 C++11通用属性

一、编译器的通用属性 随着C语言的演变和编译器的发展&#xff0c;人们常常发现C的标准提供的语言能力不能完全满足要求&#xff0c;因此各大编译器厂商为了满足客户需求&#xff0c;设计出一系列语言扩展来扩展语法&#xff0c;比较常见的就是“属性”。 “属性”是作用于实…

[rk3308]源码编译

执行自动化 ./build.sh &#xff08;1&#xff09;报 awk: line 2: function strtonum never defined Build uboot failed!解决 sudo apt install gawk&#xff08;2&#xff09;报 /bin/sh: 1: lz4c: not found sudo apt-get install liblz4-tool&#xff08;3&#xff09…

数组常用方法

1、filter 筛选 筛选数组中带有某个id的对象 let list[{id:1,name:111},{id:2,name:222},{id:3,name:333},]; let alist.filter((item)>{return item.id1 }); console.log(a)2、findIndex var idx list.findIndex((item) > {return item 2;});返回的idx是该元素在数组…

速达软件任意文件上传漏洞复现

简介 速达软件专注中小企业管理软件,产品涵盖进销存软件,财务软件,ERP软件,CRM系统,项目管理软件,OA系统,仓库管理软件等,是中小企业管理市场的佼佼者,提供产品、技术、服务等信息,百万企业共同选择。速达软件全系产品存在任意文件上传漏洞,未经身份认证得攻击者可以通过此漏…

线上超市小程序可以做什么活动_提升用户参与度与购物体验

标题&#xff1a;线上超市小程序&#xff1a;精心策划活动&#xff0c;提升用户参与度与购物体验 一、引言 随着移动互联网的普及&#xff0c;线上购物已经成为人们日常生活的一部分。线上超市作为线上购物的重要组成部分&#xff0c;以其便捷、快速、丰富的商品种类和个性化…

ROS小练习——服务调用

目录 一、服务名称与消息的获取 二、代码案例 1、C 2、python 三、编译运行 1、配置cmakelist 2、运行 一、服务名称与消息的获取 rosservice list rosservice type /spawn rossrv info turtlesim/Spawn 二、代码案例 1、C //包含头文件 #include "ros/ros.h&qu…