synchronized and ReentrantLock

ReentrantLock在加锁和内存上提供的语义与内置锁相同,此外它还提供了一些其他功能,包括定时的锁等待、可中断的锁等待、公平性,以及实现非块结构的加锁。ReentrantLock在性能上似乎优于内置锁,其中在Java 6中略有胜出,而在Java 5.0中则是远远胜出。那么为什么不放弃synchronized,并在所有新的并发代码中都使用ReentrantLock?事实上有些作者已经建议这么做,将synchronized作为一种“遗留”的结构,但这会将好事情变坏。

与显式锁相比,内置锁仍然具有很大的优势。内置锁为许多开发人员所熟悉,并且简洁紧凑,而且在许多现有的程序中都已经使用了内置锁——如果将这两种机制混合使用,那么不仅令人困惑,也容易发生错误。ReentrantLock的危险性比同步机制要高,如果忘记在finally块中调用unlock,那么虽然代码表面上能正常运行,但实际上已经埋下了一颗定时炸弹,并很有可能伤及其他代码。仅当内置锁不能满足需求时,才可以考虑使用ReentrantLock。

未来更有可能提升synchronized而不是ReentrantLock的性能。因为synchronized是JVM的内置属性,它更会执行一些优化,例如对线程封闭的锁对象的锁消除优化,通过增加锁的粒度来消除内置锁的同步,而如果通过基于类库的锁来实现这些功能,则可能性不大。除非将来需要在Java 5.0上部署应用程序,并且在该平台上确实需要ReentrantLock包含的可伸缩性,否则就性能方面来说,应该选择synchronized而不是ReentrantLock。

——《Java并发编程实战》