JAVA的锁总结

观点1

引用:http://www.majin163.com/2014/03/17/synchronized2/

Q1: synchronized到底有多大开销?与CAS这样的乐观并发控制相比如何?

从上述四个锁的原理以及加速顺序我们不难发现,synchronzied在没有锁冲突的前提下最小开销为一个CAS+栈变量维护(lock record)+一个赋值指令,有锁冲突时需要维护一个Montor对象,通过Moinitor对象维护锁队列,这种情况下涉及到线程阻塞和唤醒,开销很大。

Synchronized大多数情况下没有CAS高效,因为synchronized的最小开销也至少包含一个CAS操作。CAS和synchronized实现的多线程自加操作性能对比见上一篇博客。

Q2:怎样使用synchronized更加高效?

使用synchronized要遵从上篇博客中提到的三个原则,另外如果业务场景允许使用CAS,倾向使用CAS,或者JDK提供的一些乐观并发容器(如ConcurrentLinkedQueue等),也可以先用synchronized将业务逻辑实现,之后做针对性的性能优化。

Q3:与ReentrantLock(JDK1.5之后提供的锁对象)一类的锁相比有什么优劣?

ReentrantLock代表了JDK1.5之后由JAVA语言实现的一系列锁的工具类,而synchronized作为JAVA中的关键字,是由native(根据平台有所不同,一般是C)语言实现的。ReentrantLock虽然也实现了 synchronized中的几种锁优化技术,但与synchronized相比,性能未必好,毕竟JAVA语言效率和native语言效率比大多数情况总有不如。ReentrantLock的优势在于为程序员提供了更多的选择和更好地扩展性,比如公平性锁和非公平性锁,读写锁,CountLatch等。

细心地人会发现,JDK1.6中的并发容器大多数都是用ReentrantLock一类的锁对象实现。例如LinkedBlockingQueue这样的生产者消费者队列,虽然也可以用synchronized实现,但是这种队列中存在若干个互斥和同步逻辑,用synchronized容易使逻辑变得混乱,难以阅读和维护。

总结一点,在业务并发简单清晰的情况下推荐synchronized,在业务逻辑并发复杂,或对使用锁的扩展性要求较高时,推荐使用ReentrantLock这类锁。

Q5:可以对synchronized做哪些优化?

通过介绍synchronized的背后实现,不难看出synchronized本身已经经过了高度优化,而且除了JVM运行时的锁优化外,JAVA编译器还会对synchronized代码块做一些额外优化,例如对肯定不会发生锁竞争的synchronized进行锁消除,或频繁对一个对象进行synchronized时可以锁粗化(如synchronzied写在for循环内时,可以优化到外面),因此程序员在使用synchronized时需要注意的就是上篇博客中提到的三点原则,尤其是控制synchronzied的代码量,将无需互斥执行的代码尽量移到synchronzed之外。

观点2

http://stackoverflow.com/questions/21102592/synchronized-vs-reentrantlock-vs-atomicinteger-execution-time

  1. the version of Java. Java 5.0 was much faster for ReentrantLock, Java 7 not so much
  2. the level of contention. synchronized works best (as does locking in general) with low contention rates. ReentrantLock works better with higher contention rates. YMWV
  3. how much optimisation can the JIT do. The JIT optimise synchronized in ways ReentrantLOck is not. If this is not possible you won’t see the advantage.
  4. synchronized is GC free in it’s actions. ReentrantLock can create garbage which can make it slower and trigger GCs depending on how it is used.

观点3

http://ibruce.info/2013/12/07/java-interview-questions-concurrency/
当时我说synchronized在今后的JVM(JIT)优化的可能性比ReentrantLock大,回来后我翻翻资料,发现在ReentrantLock 和synchronized还真有一些需要了解的知识,所以特别整理下发给大家。
1.为什么JUC框架出现LOCK?
ReentrantLock并不是替代synchronized的方法,而是当内置锁不适用时,作为一种可选的高级功能。
2.那么Synchronized有哪些缺点?
①. 只有一个condition与锁相关联,这个condition是什么?就是synchronized对针对的对象锁。
②. synchronized无法中断一个正在等待获得锁的线程,也即多线程竞争一个锁时,其余未得到锁的线程只能不停的尝试获得锁,而不能中断。这种情况对于大量的竞争线程会造成性能的下降等后果。可见ReentrantLock 是对synchronized补充。
3.我们面对ReentrantLock和synchronized改如何选择?
Synchronized相比Lock,为许多开发人员所熟悉,并且简洁紧凑,如果现有程序已经使用了内置锁,那么尽量保持代码风格统一,尽量不引入Lock,避免两种机制混用,容易令人困惑,也容易发生错误。
在Synchronized无法满足需求的情况下,Lock可以作为一种高级工具,这些功能包括“可定时的、可轮询的与可中断的锁获取操作,公平队列,以及非块结构的锁”否则还是优先使用Synchronized。
最后,未来更可能提升Synchronized而不是Lock的性能,因为Synchronized是JVM的内置属性,他能执行一些优化,例如对线程封闭的锁对象的锁消除优化,通过增加锁的粒度来消除内置锁的同步,而如果基于类库的锁来实现这些功能,则可能性不大。

总结

Synchronized是jvm内置的操作,从JVM优化的角度来说,优先考虑的,但是在复杂的同步结构下,ReentrantLock和相关的锁的使用起来更加方便。性能方面,不同版本的jvm性能不同,总体来说ReentrantLock应用层做好,不依懒与JVM实现的优化,很方便使用。Synchronized在比较简单的同步结构下,强烈建议使用。
一张jvm锁升级的图
这里写图片描述
其他参考文档

http://developer.51cto.com/art/201111/304378.htm
http://developer.51cto.com/art/201111/304387.htm
http://blog.csdn.net/hengyunabc/article/details/28126139
http://blog.csdn.net/chen77716/article/details/6641477

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小小她爹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值