观点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
- the version of Java. Java 5.0 was much faster for ReentrantLock, Java 7 not so much
- the level of contention. synchronized works best (as does locking in general) with low contention rates. ReentrantLock works better with higher contention rates. YMWV
- 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.
- 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