java中synchronized与Lock的异同
前言
synchronized和Lock通过互斥保障原子性,能够保护共享数据以实现线程安全,其作用包括保障原子性、可见性、有序性
常见问题
在平时聊天或者面试过程中,可能会被问到,既然已经有了synchronized了,为什么JSR166小组花这么多时间来开发j.u.c的Lock框架呢,换句话说就是内部锁和显示锁之前有什么区别?
分析
synchronized(内部锁)
java平台中的任何一个对象都有唯一一个与之关联的锁,这种锁称为监视器(Monitor)或者内部锁(Intrinsic Lock),内部锁是通过synchronized关键字实现的,可以用来修饰方法(同步方法、静态方法)、代码块(临界区)
Lock(显示锁)
JDK1.5开始引入的排他锁,默认实现是ReetrantLock,作为一种线程同步机制,其拥有和synchronized相同的语义,并且还提供了一些synchronized不具备的特性
差异
从本质上来讲
synchronized是在JVM层面实现的,
ReetrantLock是java API层面实现的排它锁,系统无法自动释放锁,需要在代码中的finally子句中显示释放,否则会出现锁泄漏
从安全上来讲
内部锁在退出临界出时,会自动释放锁,不会导致锁泄漏
外部锁如果未主动释放锁或者释放代码在finally子句中,容易导致锁泄漏
从使用上来讲
synchronized可以修饰方法,修饰代码块,但是内部锁的申请与释放只能在一个方法内进行,因为代码无法跨方法
Lock,只能修饰代码块,但是它可以发挥面向对象编程的灵活性,显示锁的申请在一个方法,在另一个方法里释放锁
在锁的调度方面
内部锁公平锁,显示锁即支持非公平也支持公平锁
在问题定位方面
线程转储可能无法包含显示锁的相关信息,从而导致问题定位困难。比如果在JDK1.5下线程转储中会包含内部锁的相关信息,不包含显示锁的信息
从性能方面方面
等待同一把内部锁的线程,都在同一个等待队列中,等待系统调度,而ReentrantLock锁,可以通过Condition条件变量,实现分组等待的效果,所以性能表现上更好一些
从其它特性方面
当一个线程在等待获取一个锁时,因为线程活性故障导致其永远无法获取得锁时,使用内部锁的线程会一直傻傻的等待一个无法获得的锁,换句话说,内部锁缺少可中断的特性,
显示锁它拥有与内部锁相同的并发性和内存主义,但是添加了轮询锁、定时锁等候、可中断锁等候一些新特性,使其在激烈争用情况下表现出更好的性能,因为当多线程访问共享资源时,JVM可以将更多的时间用于执行线程上,而不是浪费时间在线程调度上。
- 轮询锁意味着,ReentrantLock支持公平锁,可以通过轮询的方式依次获取锁
- 定时锁等候意味着,线程在N长时间之内无法获取到锁,就会返回false ,表示获取锁失败,tryLock方法,不会像内部锁一样痴痴的等待一个没有结果的未来
- 可中断锁等待,意味着ReentrantLock提供了一种能够中断等待锁的线程的机制,通过
lock.lockInterruptibly()来实现这个机制。
如何选择
如果你使用的是JDK1.5的话,在争用不高的时候可以使用内部锁,在争用高的情况下,建议使用显示锁
如果你使用的是JDK1.5+的版本,随着对内部锁的优化(锁消除、锁粗化、偏向锁、自适应锁),两都之间的性能差异已经缩小了很多,如果后期内部锁的这些优化可以应用到显示锁的话,那性能可能就会有很大差距了。
总体上来说,在资源竞争不激烈的情形下,性能稍微比synchronized差点点。但是资源竞争非常激烈的时候,synchronized的性能会下降很多,而ReentrantLock的性能表现仍然比较稳定。
结束语
在工作中,为了保证线程安全我们不一定要使用锁,可以使用一些轻量级的同步工具或者无锁的框架和工具,来提升应用的性能。
java中synchronized与Lock的异同的更多相关文章
- JAVA中synchronized和lock详解
目前在Java中存在两种锁机制:synchronized和Lock,Lock接口及其实现类是JDK5增加的内容,其作者是大名鼎鼎的并发专家Doug Lea.本文并不比较synchronize ...
- Java中Synchronized和Lock的使用
Lock的锁定是通过代码实现的,而 synchronized 是在 JVM 层面上实现的 synchronized在锁定时如果方法块抛出异常,JVM 会自动将锁释放掉,不会因为出了异常没有释放锁造成线 ...
- Java中synchronized和Lock的区别
synchronized和Lock的区别synchronize锁对象可以是任意对象,由于监视器方法必须要拥有锁对象那么任意对象都可以调用的方法所以将其抽取到Object类中去定义监视器方法这样锁对象和 ...
- Java并发指南4:Java中的锁 Lock和synchronized
Java中的锁机制及Lock类 锁的释放-获取建立的happens before 关系 锁是java并发编程中最重要的同步机制.锁除了让临界区互斥执行外,还可以让释放锁的线程向获取同一个锁的线程发送消 ...
- java中synchronized的用法详解
记下来,很重要. Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码. 一.当两个并发线程访问同一个对象object中的这个synchron ...
- java中synchronized的使用方法与具体解释
Java语言的keyword.当它用来修饰一个方法或者一个代码块的时候,可以保证在同一时刻最多仅仅有一个线程运行该段代码. 一.当两个并发线程訪问同一个对象object中的这个synchronized ...
- Java 中 synchronized的用法详解(四种用法)
Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码.本文给大家介绍java中 synchronized的用法,对本文感兴趣的朋友一起看看吧 ...
- java中 synchronized 的使用,确保异步执行某一段代码。
最近看了个有关访问网络url和下载的例子,里面有几个synchronized的地方,系统学习下,以下内容很重要,记下来. Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一 ...
- JAVA 中 synchronized 详解
看到一篇关于JAVA中synchronized的用法的详解,觉得不错遂转载之..... 原文地址: http://www.cnblogs.com/GnagWang/archive/2011/02/27 ...
随机推荐
- Linux性能分析:生产环境服务器变慢,诊断思路和性能评估
Linux性能分析:生产环境服务器变慢,诊断思路和性能评估 一.整机:top 二.CPU:vmstat 所有CPU核信息 每个进程使用CPU的用量分解信息 三.内存:free 四.硬盘:df 五.磁盘 ...
- Fastjson使用实例
Fastjson使用实例 一.FastJson使用范例 1.1FastJson三个核心类 1.2Maven依赖 1.3Scala API 1.3.1反序列化 1.3.2序列化 1.4Java API ...
- Maven 私服(Nexus)
@[toc](Maven 私服(Nexus)) 1.Nexus 简介 Nexus是Maven仓库管理器,也可以叫Maven的私服.Nexus是一个强大的Maven仓库管理器,它极大地简化了自己内部仓库 ...
- Spring,Spring MVC,MyBatis,Hibernate总结
将之前学习的框架知识进行了UML图总结,若有错误或不当之处,劳烦朋友们指正,会及时作出修改和补充: [toc] Spring Spring MVC MyBatis,Hibernate
- Spark SQL 自定义函数类型
Spark SQL 自定义函数类型 一.spark读取数据 二.自定义函数结构 三.附上长长的各种pom 一.spark读取数据 前段时间一直在研究GeoMesa下的Spark JTS,Spark J ...
- 浅聊ARP
今天借用思科公司的Cisco Packet Tracer Student这款软件浅聊ARP 什么是ARP? ARP即地址解析协议(Address Resolution Protocol),是根据Ip地 ...
- AJAX传值中文乱码
AJAX传值时采用的是UTF-8编码格式,客户端中文字符传输到服务器端时,如果服务器编码格式或者所采用的MVC框架的编码格式不是UTF-8,则很可能会出现中文乱码.解决办法如下: 客户端用js函数en ...
- markdown 编辑器使用教程---字体、颜色、表格换行、链接等
资源池: 绿色版markdown编辑器:点击这里 提取码:ftf9 1.标题 #一级标题 ##二级标题 ###三级标题 ####四级标题 #####五级标题 ######六级标题 一级标题 二级标题 ...
- 理解了这三点,才敢说自己会写Python代码
某同学应聘Python岗位被录用.上班第一天,Leader吩咐他写一个获取次日日期信息的函数.该同学信心满满地写下了这样一段代码, 然后就没有然后了. import time def get_next ...
- Wormholes (spfa)
一种路是双向的,路的长度是正值:另一种路是单向的,路的长度是负值: 如果有负环输出YES:否则输出NO:不同的路可能有相同的起点和终点:必须用邻接表 While exploring his many ...