在 synchronized 和 Reentrantlock 之间进行选择

                  在 synchronized 和 Reentrantlock 之间进行选择

ReentrantLock与内部锁 在加锁和内存语义上是 相同的,在以下附加特性的语义上也相同,比如定时锁的等待,可中断锁的等待,公平性,以及实现非块结构的 锁。 ReentrantLock的性能看起来胜过内部锁,Java6中时略微胜过,而Java5.0中是大大超越。那么为什么不放弃使用synchronized,鼓励大家都使用新的并发ReentrantLock呢?

事实上的确有一些作者建议如此,把synchronized 作为 遗留 结构。 但是这会把好事情变坏。
内部锁相比于显式锁仍然具有很大的优势。这个标识更为人们所熟悉,也更简洁,而且很多现有的程序已经在使用内部锁了 混合这两者会造成混淆,反而并更易发生错误。ReentrantLock绝对是最危险的同步工具;如果你忘记在finally块中调用unlock, 你的代码将很可能看起来能够正常运行,但是已经埋下定时炸弹,并很有可能伤及无辜。 在内部锁不能满足需求,需要使用ReentrantLock的情况下才应该使用。


在Java5.0中,内部锁与ReentrantLock相比,还具有另外优点:线程转储能够显示哪些个调用框架获得了哪些锁,并能够识别发生了死锁的那些线程。 JVM 并不知道哪个线程持有 ReentrantLock,因此 在调试使用Reentrant工Jock的线程间存在的问题时, 无法从中获得帮助。这个问题在Java6中得到了解决,它提供了一个管理和调试接口,锁可以使用这个接口进行注册,并通过其他管理和调试接口,从线程转储中得到 ReentrantLock的加锁信息。这些用于调试的消息的可用性对于synchronized 是有优势的,即使它们大部分为即时消息:线程转储中的加锁信息解除了很多程序员的恐慌。 ReentrantLock的非块结构的特性仍然意味着获取锁不能依赖于特定的核结构,这一点与 内部锁是不同的。

未来的性能改进可能更倾向于synchronized而不是ReentrantLock。因为synchronized是内置于JVM的, 它能够进行优化, 比如对线程限制的锁对象的锁省略( lock elision), 粗化锁来减小内部锁的同步性(参见11.3.2):使用基于类库的锁来实现这些看起来可能性不大。 除非你正发布在Java 5.0上, 对于未来, 除非你的平台对 ReentrantLock的可伸缩性有切实的需要, 否则就性能的原因选择ReentrantLock而不 是synchronized, 这不是正确的决定。

猜你喜欢

转载自blog.csdn.net/xiao__jia__jia/article/details/81667346