synchronized与(ReentrantLock)Lock的对比区别

2023-11-11

 
 
类别
synchronized
Lock
存在层次
Java关键字,属于原生语法层面 需要jvm实现
而Lock它是JDK 1.5之后提供的API层面的互斥锁,需要lock()和unlock()方法配合try/finally语句块来完成
锁的释放
1.以获取锁的线程执行完同步代码块,释放锁
2.线程执行发生异常,jvm会让线程释放锁
在finally必须释放锁,不然容易造成线程死锁
锁的获取
假设A线程获得锁,B线程等待,如果A线程阻塞,B线程会一直等待
分情况而定,Lock有多个锁获取方式,可以尝试获取锁,线程可以不用一直等待。
锁的状态
无法判断
可以判断
锁类型
可重入 不可中断 非公平
可重入 可中断 可公平(两者皆可)
性能
少量同步
大量同步
区别如下:

 

1.Lock是显示锁(手动开启和关闭锁), synchronized时隐式锁,出来作用域自动释放
 
2.Lock只有代码块锁,synchronized有代码块锁和方法锁
 
3.使用Lock锁,JVM将花费较少的时间来调度线程,性能更好。并且具有更好的扩展性(提供了更多子类)
 
4.lock是一个接口,而synchronized是java的一个关键字,synchronized是内置的语言实现;
 
5.异常是否释放锁: 
    synchronized在发生异常时候会自动释放占有的锁,因此不会出现死锁;而lock发生异常时候,不会主动释放占有的锁,必须手动unlock来释放锁,可能引起死锁的发生。(所以最好将同步代码块用try catch包起来,finally中写入unlock,避免死锁的发生。)
 
6.是否响应中断 
    lock等待锁过程中可以用interrupt来中断等待,而synchronized只能等待锁的释放,不能响应中断;
 
7.是否知道获取锁 
    Lock可以通过trylock来知道有没有获取锁,而synchronized不能;
 
8.Lock可以提高多个线程进行读操作的效率。(可以通过readwritelock实现读写分离)
 
9.在性能上来说,如果竞争资源不激烈,两者的性能是差不多的,而当竞争资源非常激烈时(即有大量线程同时竞争),此时Lock的性能要远远优于synchronized。所以说,在具体使用时要根据适当情况选择。
 
10.synchronized使用Object对象本身的wait 、notify、notifyAll调度机制,而Lock可以使用Condition进行线程之间的调度
//Condition定义了等待/通知两种类型的方法
Lock lock=new ReentrantLock();
Condition condition=lock.newCondition();
...
condition.await();
...
condition.signal();
condition.signalAll();

 

1、synchronized和lock的用法区别

synchronized:在需要同步的对象中加入此控制,synchronized可以加在方法上,也可以加在特定代码块中,括号中表示需要锁的对象。
lock:一般使用ReentrantLock类做为锁。在加锁和解锁处需要通过lock()和unlock()显示指出。所以一般会在finally块中写unlock()以防死锁。
 

2、synchronized和lock性能区别

synchronized是托管给JVM执行的, 
而lock是java写的控制锁的代码。
在Java1.5中,synchronize是性能低效的。因为这是一个重量级操作,需要调用操作接口,导致有可能加锁消耗的系统时间比加锁以外的操作还多。相比之下使用Java提供的Lock对象,性能更高一些。
但是到了Java1.6,发生了变化。synchronize在语义上很清晰,可以进行很多优化,有适应自旋,锁消除,锁粗化,轻量级锁,偏向锁等等。导致在Java1.6上synchronize的性能并不比Lock差。官方也表示,他们也更支持synchronize,在未来的版本中还有优化余地。

 

2种机制的具体区别: 
synchronized原始采用的是CPU悲观锁机制,即线程获得的是独占锁。独占锁意味着其他线程只能依靠阻塞来等待线程释放锁。而在CPU转换线程阻塞时会引起线程上下文切换,当有很多线程竞争锁的时候,会引起CPU频繁的上下文切换导致效率很低。
而Lock用的是乐观锁方式。所谓乐观锁就是,每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。乐观锁实现的机制就是CAS操作(Compare and Swap)。我们可以进一步研究ReentrantLock的源代码,会发现其中比较重要的获得锁的一个方法是compareAndSetState。这里其实就是调用的CPU提供的特殊指令。
现代的CPU提供了指令,可以自动更新共享数据,而且能够检测到其他线程的干扰,而 compareAndSet() 就用这些代替了锁定。这个算法称作非阻塞算法,意思是一个线程的失败或者挂起不应该影响其他线程的失败或挂起的算法。

 

3、synchronized和lock用途区别

synchronized原语和ReentrantLock在一般情况下没有什么区别,但是在非常复杂的同步应用中,请考虑使用ReentrantLock,特别是遇到下面2种需求的时候。

 

1.某个线程在等待一个锁的控制权的这段时间需要中断 
2.需要分开处理一些wait-notify,ReentrantLock里面的Condition应用,能够控制notify哪个线程 
3.具有公平锁功能,每个到来的线程都将排队等候
下面细细道来……

 

先说第一种情况,ReentrantLock的lock机制有2种,忽略中断锁和响应中断锁,这给我们带来了很大的灵活性。比如:如果A、B 2个线程去竞争锁,A线程得到了锁,B线程等待,但是A线程这个时候实在有太多事情要处理,就是一直不返回,B线程可能就会等不及了,想中断自己,不再等待这个锁了,转而处理其他事情。这个时候 ReentrantLock就提供了2种机制:可中断/可不中断 
第一,B线程中断自己(或者别的线程中断它),但是ReentrantLock不去响应,继续让B线程等待,你再怎么中断,我全当耳边风(synchronized原语就是如此); 
第二,B线程中断自己(或者别的线程中断它),ReentrantLock处理了这个中断,并且不再等待这个锁的到来,完全放弃。
 
优先使用顺序:
Lock -> 同步代码块 (已经进入了方法体,分配了相应资源)-> 同步方法(在方法体之外)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

synchronized与(ReentrantLock)Lock的对比区别 的相关文章

  • Java 迭代器获取下一个而不递增

    我正在用 Java 编写以下循环 对于每个循环 我想访问链表 r 的当前元素和下一个元素 List
  • 使用比较器对对象进行排序给出空指针

    我正在尝试对包含 3 张卡的 ArrayList 进行排序 我正在用比较器来做这件事 这是否太过分了 Card getRank 返回 2 到 14 之间的整数 我完全不知道哪里出了问题 我之前已经成功完成了这个 并与我的其他代码进行了比较
  • Antlr 处理异常

    我使用 Antlr 3 和 AST 树开发了一个复杂的语法 ANTLR 生成词法分析器和解析器 问题是 例如 当用户输入无效的语法时 该语法需要 用户没有输入此内容 然后在我的 Eclipse IDE 中出现以下异常 line 1 24 m
  • eclipse juno 打开时出错

    在安装 Eclipse 并正常工作一年多后 我今天打开 Eclipse Juno 并在打开工作区时收到一条错误消息 我使用的是 Windows 8 64 位 Java 64 位和 Eclipse 64 位 此后我尝试重新安装 Java 和
  • 匿名内部类显示不正确的修饰符

    据我了解 以下代码应该打印true作为输出 但是 当我运行这段代码时 它正在打印false 来自 Java 文档15 9 5 匿名类 https docs oracle com javase specs jls se8 html jls 1
  • Java 弱哈希映射 - 需要根据值的弱点而不是键来删除条目

    所以JavaWeakHashMap让我们创建一个映射 如果其键变弱 则删除该映射的条目 但是我怎样才能创建一个Map 当它的条目被删除时values地图上变弱了 我想使用映射的原因是作为全局哈希表 它根据对象的 ID 跟踪对象 ID gt
  • 包含小时、分钟和秒的周期[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我需要一个代表年 月 周 日 小时 分钟 秒的间隔数据类型 前三年 年 月 日 可以用Period最后
  • 按对象值分组,统计后按最大对象属性设置组键

    我设法使用 Java 8 Streams API 编写了一个解决方案 该解决方案首先按对象 Route 的值对列表进行分组 然后计算每组中的对象数量 它返回一个映射 Route gt Long 这是代码 Map
  • Selenium - 保存网站,包括所有图像、css、dom

    我想使用 firefox 或 chrome 访问带有 selenium 的页面 当页面加载时 我想从页面下载所有图像 css dom 我想存储每张图像 就像我在其中找到它们一样 chrome gt Tools gt Development
  • 黄瓜与 Micronaut

    我正在尝试将 Cucumber 与 Micronaut 一起使用 但当我尝试将其与 Cucumber 一起使用时 MicronautTest 注释根本不起作用 未注入 theApple 请参阅下面的代码 如果我在没有黄瓜的情况下运行它就可以
  • 如何使用 Spring Security 跨多个基于 JVM 的应用程序实现单点登录

    我目前正在尝试跨多个基于 JVM Grails Servlet 的 Web 应用程序实现单点登录解决方案 这些应用程序目前都部署在同一个 servlet 容器 当前是 Tomcat 但不想将我的解决方案仅限于 Tomcat 中 所有 Web
  • 可以混合使用 JVM 语言吗?即:Groovy 和 Clojure

    我知道你可以轻松地混合groovy java clojure java 无论什么JvmLang java 这是否也意味着我也可以让 clojure 和 groovy 代码进行交互 如果我使用 Grails 或 jRoR 我也可以在该环境中使
  • 如何将 wsdl 内部架构设置为 Jaxb2Marshaller 以验证我所做的每篇文章?

    我正在使用 SOAP Web 服务 在调用它之前我必须验证每个 xml 帖子 所以我正在使用 The CXF codegen 插件生成POJO树结构 第三部分 wsdl xxxx soap service wsdl 一个类实现Web服务网关
  • 如何减少 JSF 中的 javax.faces.ViewState

    减少 JSF 中视图状态隐藏字段大小的最佳方法是什么 我注意到我的视图状态约为 40k 这会在每次请求和响应时下降到客户端并返回到服务器 特别是到达服务器时 这对用户来说会显着减慢 我的环境 JSF 1 2 MyFaces Tomcat T
  • 如何获取队列中的第 n 个项目?

    我的应用程序中有许多队列和优先级队列 我想轻松访问这些队列中的第 n 个项目 但没有看到使用 API 实现此目的的简单方法 我想我可以创建一个Iterator并迭代到第 n 个元素或使用toArray index 但似乎应该有一个更简单的方
  • WebSocketStompClient 将无法连接到 SockJS 端点

    我正在尝试新的 从版本 4 2 开始 java STOMP 客户端支持 我的出发点是入门指南 使用 WebSocket 构建交互式 Web 应用程序 http spring io guides gs messaging stomp webs
  • 在 Java 服务器中验证 Windows 用户

    我正在开发一个用 Java 编写的服务器和一个在同一网络上的 Windows 计算机上运行的客户端 用 Net 编写的桌面应用程序 我希望进行一些基本身份验证 以便服务器可以确定运行客户端的用户的用户名 而不需要用户在客户端中重新输入其 W
  • 如何确保超类的子类方法的线程安全?

    我参加了一次面试 并被要求为以下要求设计一个课程 假设我有一个 A 类 它可以有任意数量的子类 即子类 类 A 有一个名为 doSomething 的方法 该方法是同步的 要求是 A 的所有子类都是强制性的重写 doSomething me
  • 如何正确使用Google Calendar API Events.Insert命令?

    所以我一直使用REST方法来调用Google的API 我需要将事件插入到我拥有 ID 的特定日历中 这是我发送的 POST 请求 地址 https www googleapis com calendar v3 calendars https
  • 根据 Java 环境变量中的值创建使用 @JsonIgnore 的自定义注释

    我需要创建一个新的注释 用于在环境变量设置时忽略输出 JSON 文件中的字段var false 我尝试使用JsonAnnotationIntrospector 但无法获得预期的输出 public class Vehicle String v

随机推荐

  • 评估指标 -- Precision(查准率), Recall(查全率)和F1 score; PR曲线和mAP; ROC曲线和AUC

    Precision Recall 和 F1 score Precision 查准率 精确率 Recall 查全率 召回率 查准率和查全率是互相影响的 理想情况是希望两者都高 但是一般情况下查准率高 查全率就低 查全率高 查准率就低 如果是做
  • 蓝桥杯---算法训练 大等于n的最小完全平方数(Java解法)

    题目 问题描述 输出大等于n的最小的完全平方数 若一个数能表示成某个自然数的平方的形式 则称这个数为完全平方数 Tips 注意数据范围 输入格式 一个整数n 输出格式 大等于n的最小的完全平方数 样例输入 71711 样例输出 71824
  • 组合模式-

    定义 也称为整体 部分模式 它的宗旨是通过将单个对象 叶子节点 和组合对象 树枝节点 用相同的接口进行表示 适用场景 1 希望客户端可以忽略组合对象与单个对象的差异时 2 对象层次具备整体和部分 呈树形结构 如树形菜单 操作系统目录结构 公
  • 电脑只能登录微信?但却打不开网页?不能上网怎么办?ip地址和DNS出问题了无法上网怎么办?

    描述一下问题 昨天使用了一些代理梯子 直接关机 没有关闭那个软件 今天打开电脑就出问题了 只能登录微信 但却打不开网页 今天查了很多资料都没有解决 花了2个多小时 终于可以上网了 解决办法 找到 控制面板 网络和Internet 里面的 网
  • 计算机的桌面的路径,如何设置电脑保存路径在桌面上?

    我们在使用电脑时一般都会把系统安装到C盘 而很多的桌面图标也随之产生在C盘 当桌面文件越来越多是 不仅影响开机速度 同 时我们的电脑会很卡 当系统崩溃需要重装电脑时 我们总是要通过各种办法备份桌面 如果我们把桌面路径改到其他盘符 这些烦恼就
  • 2021-06-30 暑期实训开发日志3——山大云服务器配置anaconda pytorch

    暑期实训开发日志3 山大云服务器配置anaconda pytorch 一 安装anaconda 1 获取Anaconda安装脚本 2 安装 3 环境配置 二 creat新环境并连接pycharm 三 下载pytorch 可能会遇到的问题和解
  • giaogiao教你用c语言在屏幕上打印各种图案

    今天我们用c语言来实现在屏幕上打印用 组成的图案 首先呢 我们从简单的开始 输出自定义行数的矩形 我定义了三个变量 用for循环做了一个嵌套 用n来限制i j 从而控制输出图案的大小 搞定 你看我屌么 哈哈哈哈 这只是开始 我试试来输出自定
  • win8.1 pro-64位下安装配置MinGW—64位

    1 下载MinGW w64位 http mingw w64 org doku php 点击Downloads 说明 这边使用的是在线安装方式 在网站里可以看到他安装后的文件夹 2 安装 运行mingw w64 install exe 欢迎界
  • 如何使用QMessageBox(用法举例)

    如何使用QMessageBox 用法举例 QMessageBox是Qt编程中常用的类 使用方便 下面给出该类的普通用法实例 希望对你有所帮助 1 包含头文件 include
  • 西门子S7-1200实现先进先出(FIFO)循环存储

    目录 一 使用数组存储 通过更改存入和取出的索引实现 使用LAD语言 SCL语言组合实现 1 新建函数块 FB块 2 基础变量声明 3 开始写程序 4 完整程序 END 一 使用数组存储 通过更改存入和取出的索引实现 使用LAD语言 SCL
  • VS 2022 Format on Save

    如果不将上图中的 Enable Format Document 设置为 false 则保存时 会将代码中注释的格式修改
  • 2.mybatis-plus入门案例

    2 mybatis plus入门案例 mybatis plus入门案例 2 mybatis plus入门案例 一 创建并初始化数据库 1 创建数据库 2 创建 User 表 二 初始化工程 三 添加依赖 1 引入依赖 2 idea中安装lo
  • Kali:SYN简单泛洪攻击(DOS攻击)

    Kali SYN简单泛洪攻击 原理解析 工具原理解析 正式攻击思路 攻击演示 原理解析 SYN泛洪攻击 利用三次握手的缺陷 让tcp连接始终处于未成功连接的半连接状态 攻击机仅发出第一次握手 不对返回信息进行确认 服务器由于需要不断处理连接
  • ESP8266教程4 — ESP8266 智能配网

    按照前面的教程演示 如果想要给esp8266模块联网 可以使用AT指令加上SSID和密码即可以让模块连接到无线网络上 但是对于一个投向了市场的产品而言 消费者购买了你的一个可以联网的智能产品 当他们想要使用的时候总不能让消费者也使用AT指令
  • Java多线程技术

    Java多线程技术 Java中如何实现多线程 继承Thread类 实现Runnable接口 实现Callable接口 通过继承Thread类实现多线程 继承Thread类实现多线程的步骤 继承Thread类 重写方法run 来完成其操作的
  • flutter 自定义微信/支付宝密码输入框

    如图 项目需求需要实现以上效果 思路解析 1 可以用dialog来实现 2 可以用一个新statfulWidget实现 因为不大熟悉dialog 故用了一个新的statefulWidget来实现页面效果 直接上代码 功能 描述 设置密码弹框
  • JavaWeb中JSP和Servlet的相关知识

    JSP注释代码 引入JAVA包 举例 JSP中的JAVA代码块 在此代码块中可以定义变量和方法 定义的变量为局部变量 定义表达式 只能定义变量 且定义的变量为成员变量 输出表达式 直接向网页显示包含内容的value 局部变量 执行 JSP时
  • jQuery AJAX获取JSON数据解析多种方式示例

  • 阿里云云计算ACP学习笔记(Wakin老师)——云计算基础

    1 云计算最早可追溯到2012年 2 传统IT系统面临的问题 1 资源利用率低 传统服务器的资源占用率不均衡 个别在30 40 大多数在10 企业所投产的IT资源未得到有效利用 2 业务上线时间长 从设备采购开始到上架多则半年一年 3 能耗
  • synchronized与(ReentrantLock)Lock的对比区别

    类别 synchronized Lock 存在层次 Java关键字 属于原生语法层面 需要jvm实现 而Lock它是JDK 1 5之后提供的API层面的互斥锁 需要lock 和unlock 方法配合try finally语句块来完成 锁的释