当前位置: 首页 > news >正文

总结Synchronized与Lock的区别

存在层次上

synchronized: Java的关键字,在jvm层面上

Lock: 是一个接口

锁的释放

synchronized: 1、以获取锁的线程执行完同步代码,释放锁 2、线程执行发生异常,jvm会让线程释放锁

Lock: 在finally中必须释放锁,不然容易造成线程死锁

锁的获取

synchronized: 假设A线程获得锁,B线程等待。如果A线程阻塞,B线程会一直等待

Lock: 分情况而定,Lock有多个锁获取的方式,大致就是可以尝试获得锁,线程可以不用一直等待(可以通过tryLock判断有没有锁)

锁的释放(死锁产生)

synchronized: 在发生异常时候会自动释放占有的锁,因此不会出现死锁

Lock: 发生异常时候,不会主动释放占有的锁,必须手动unlock来释放锁,可能引起死锁的发生

锁的状态

synchronized: 无法判断

Lock: 可以判断

锁的类型

synchronized: 可重入 不可中断 非公平

Lock: 可重入 可判断 可公平(两者皆可)

性能

synchronized: 少量同步

Lock: 大量同步

  • Lock可以提高多个线程进行读操作的效率。(可以通过readwritelock实现读写分离)
  • 在资源竞争不是很激烈的情况下,Synchronized的性能要优于ReetrantLock,但是在资源竞争很激烈的情况下,Synchronized的性能会下降几十倍,但是ReetrantLock的性能能维持常态;
  • ReentrantLock提供了多样化的同步,比如有时间限制的同步,可以被Interrupt的同步(synchronized的同步是不能Interrupt的)等。在资源竞争不激烈的情形下,性能稍微比synchronized差点点。但是当同步非常激烈的时候,synchronized的性能一下子能下降好几十倍。而ReentrantLock确还能维持常态。

调度

synchronized: 使用Object对象本身的wait 、notify、notifyAll调度机制

Lock: 可以使用Condition进行线程之间的调度

用法

synchronized: 在需要同步的对象中加入此控制,synchronized可以加在方法上,也可以加在特定代码块中,括号中表示需要锁的对象。

Lock: 一般使用ReentrantLock类做为锁。在加锁和解锁处需要通过lock()和unlock()显示指出。所以一般会在finally块中写unlock()以防死锁。

底层实现

synchronized: 底层使用指令码方式来控制锁的,映射成字节码指令就是增加来两个指令:monitorenter和monitorexit。当线程执行遇到monitorenter指令时会尝试获取内置锁,如果获取锁则锁计数器+1,如果没有获取锁则阻塞;当遇到monitorexit指令时锁计数器-1,如果计数器为0则释放锁。

Lock: 底层是CAS乐观锁,依赖AbstractQueuedSynchronizer类,把所有的请求线程构成一个CLH队列。而对该队列的操作均通过Lock-Free(CAS)操作。

如果大家对java架构相关感兴趣,可以关注下面公众号,会持续更新java基础面试题, netty, spring boot,spring cloud等系列文章,一系列干货随时送达, 超神之路从此展开, BTAJ不再是梦想!

架构殿堂

相关文章:

  • 带你了解 java 各种锁
  • 求一个版本号的正则表达式,版本号的格式可以是1.1或1.1.2或10000这个样子的
  • 序列化和反序列化总结
  • 适配器模式
  • 运行django项目时出错
  • 何为JAVA内部类?
  • 数据库原理中的范式
  • JAVA线程池如何调优
  • 【RF库测试】Variable Should not Exist variable should exist
  • JDK8中为什么移除方法区
  • 对象是否存活,可以这样判断?
  • ETL全量多表同步简述
  • 简洁说明JVM内存区域(运行时数据区)
  • python学习day1--python基础
  • 你了解垃圾收集算法吗?
  • [原]深入对比数据科学工具箱:Python和R 非结构化数据的结构化
  • 【5+】跨webview多页面 触发事件(二)
  • 【跃迁之路】【699天】程序员高效学习方法论探索系列(实验阶段456-2019.1.19)...
  • AHK 中 = 和 == 等比较运算符的用法
  • extract-text-webpack-plugin用法
  • Git的一些常用操作
  • Java 11 发布计划来了,已确定 3个 新特性!!
  • js作用域和this的理解
  • niucms就是以城市为分割单位,在上面 小区/乡村/同城论坛+58+团购
  • rabbitmq延迟消息示例
  • React-Native - 收藏集 - 掘金
  • Redis在Web项目中的应用与实践
  • Spark RDD学习: aggregate函数
  • VUE es6技巧写法(持续更新中~~~)
  • Vue2 SSR 的优化之旅
  • 关键词挖掘技术哪家强(一)基于node.js技术开发一个关键字查询工具
  • 汉诺塔算法
  • 后端_ThinkPHP5
  • 普通函数和构造函数的区别
  • 如何胜任知名企业的商业数据分析师?
  • 通过npm或yarn自动生成vue组件
  • 掌握面试——弹出框的实现(一道题中包含布局/js设计模式)
  • “十年磨一剑”--有赞的HBase平台实践和应用之路 ...
  • 函数计算新功能-----支持C#函数
  • 你学不懂C语言,是因为不懂编写C程序的7个步骤 ...
  • ​一些不规范的GTID使用场景
  • $分析了六十多年间100万字的政府工作报告,我看到了这样的变迁
  • (06)金属布线——为半导体注入生命的连接
  • (cos^2 X)的定积分,求积分 ∫sin^2(x) dx
  • (C语言)球球大作战
  • (附源码)计算机毕业设计ssm高校《大学语文》课程作业在线管理系统
  • (力扣记录)1448. 统计二叉树中好节点的数目
  • (转)shell中括号的特殊用法 linux if多条件判断
  • (转)程序员疫苗:代码注入
  • (转)德国人的记事本
  • .htaccess配置重写url引擎
  • .NET 8.0 发布到 IIS
  • .net 后台导出excel ,word
  • .NET/C# 阻止屏幕关闭,阻止系统进入睡眠状态
  • .NetCore部署微服务(二)