Java并发之显式锁和隐式锁的区别
Java并发之显式锁和隐式锁的区别
在面试的过程中有可能会问到:在Java并发编程中,锁有两种实现:使用隐式锁和使用显示锁分别是什么?两者的区别是什么?所谓的显式锁和隐式锁的区别也就是说说Synchronized(下文简称:sync)和lock(下文就用ReentrantLock来代之lock)的区别。
本文主要内容:将通过七个方面详细介绍sync和lock的区别。通过生活case中的X二代和普通人比较大家更容易理解这两者之间的区别
Java中隐式锁:synchronized;显式锁:lock
sync和lock的区别
一:出身不同
从sync和lock的出身(原始的构成)来看看两者的不同。
Sync:Java中的关键字,是由JVM来维护的。是JVM层面的锁。
Lock:是JDK5以后才出现的具体的类。使用lock是调用对应的API。是API层面的锁
sync是底层是通过monitorenter进行加锁(底层是通过monitor对象来完成的,其中的wait/notify等方法也是依赖于monitor对象的。只有在同步块或者是同步方法中才可以调用wait/notify等方法的。因为只有在同步块或者是同步方法中,JVM才会调用monitory对象的);通过monitorexit来退出锁的。
而lock是通过调用对应的API方法来获取锁和释放锁的。
我们通过Javap命令来查看调用sync和lock的汇编指令:
编辑
从编译后的汇编指令,我们也能够清晰的看出sync关键字和lock的区别。
第一不同一句话概述:可以把sync理解为官二代或者是星二代。从娘胎出来自带光环的。Lock就是我们普通努力上进的人。
二:使用方式不同
Sync是隐式锁。Lock是显示锁
所谓的显示和隐式就是在使用的时候,使用者要不要手动写代码去获取锁和释放锁的操作。
我们大家都知道,在使用sync关键字的时候,我们使用者根本不用写其他的代码,然后程序就能够获取锁和释放锁了。那是因为当sync代码块执行完成之后,系统会自动的让程序释放占用的锁。Sync是由系统维护的,如果非逻辑问题的话话,是不会出现死锁的。
在使用lock的时候,我们使用者需要手动的获取和释放锁。如果没有释放锁,就有可能导致出现死锁的现象。手动获取锁方法:lock.lock()。释放锁:unlock方法。需要配合tyr/finaly语句块来完成。
两者用法对比如下:
编辑
用生活中的一个case来形容这个不同:官二代和普通人的你在进入机关大院的时候待遇。官二代不需要出示什么证件就可以进入,但是你需要手动出示证件才可以进入。
三:等待是否可中断
Sync是不可中断的。除非抛出异常或者正常运行完成
Lock可以中断的。中断方式:
1:调用设置超时方法tryLock(long timeout ,timeUnit unit)
2:调用lockInterruptibly()放到代码块中,然后调用interrupt()方法可以中断
生活中小case来理解这一区别:官二代一般不会做饭。都会去餐厅点餐等待着餐厅出餐。普通人的你既可以去餐厅等待,如果等待时间长的话,你就可以回去自己做饭了。
四:加锁的时候是否可以公平
Sync;非公平锁
lock:两者都可以的。默认是非公平锁。在其构造方法的时候可以传入Boolean值。
true:公平锁
false:非公平锁
生活中小case来理解这个区别:官二代一般都不排队,喜欢插队的。普通人的你虽然也喜欢插队。但是如果遇到让排队的情况下,你还是会排队的。
Lock的公平锁和非公平锁:
五:锁绑定多个条件来condition
Sync:没有。要么随机唤醒一个线程;要么是唤醒所有等待的线程。
Lock:用来实现分组唤醒需要唤醒的线程,可以精确的唤醒,而不是像sync那样,不能精确唤醒线程。
六:从性能比较
生活小case理解:在我们一般的认知中,官二代一般都是比较坑爹的吧。但是这几年也有很多官二代或者是富二代改变了态度,端正自己态度,靠自己能力而不是拼爹了。
七:从使用锁的方式比较
欢迎来聊~
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
redis实现分布式锁踩坑记录
这里主要记录项目中使用基于redis的分布式锁所遇到的问题及解决方案; 业务场景 我的业务场景是这样的,我们服务有库存模块,而我的服务又是多节点部署,要高峰期会存在库存差异,后面分析问题之后,打算采用redis实现分布式锁(主要的原因是服务已经集成了redis,不需要做额外的配置) 踩坑1. 数据库事务超时 不要感觉奇怪,分布式锁怎么会导致数据库事务超时呢?我的代码大概是这样的: 伪代码 @Transaction(readOnly=false) void update(){ do{ redis=JedisUtil.getJedis(); flag = getLock(key,redis); if(flag){ update(); } }while(true) } 当你的key长时间获取不到锁,并且数据库事务都有超时时间的限制,那么就会出现数据库事务超时问题;解决方案 数据库事务改为手动提交事务; 踩坑2. redis key过期,而业务没有执行完 我的key的过期时间设置的是30s,如果30秒业务还没有执行完毕,锁就会自动释放,锁释放之后,其它线程又会去占用锁,同样会导致问题的发生;解...
- 下一篇
golang 的不可变(Immutable)编程
不可变编程是一种编程思想。简单地说,就是对象的属性只能set一次。 ImmutableEphemeralVolume(immutable secret) 以 kubernetes 最近(2019年年底)的一个 ImmutableEphemeralVolume 为例。 我看了一下源代码,大意就是说,configmap 和 secret 在创建后不可更新。 以 secret 为例,目前(2020-04-16)secret 的定义是这样的: // Secret holds secret data of a certain type. The total bytes of the values in // the Data field must be less than MaxSecretSize bytes. type Secret struct { metav1.TypeMeta `json:",inline"` // Standard object's metadata. // More info: https://git.k8s.io/community/contributors/de...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Hadoop3单机部署,实现最简伪集群
- CentOS8编译安装MySQL8.0.19
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Mario游戏-低调大师作品
- CentOS6,CentOS7官方镜像安装Oracle11G