互斥同步

互斥同步(Mutual Exclusion & Synchronization)是一种最常见也是最主要的

并发正确性保障手段。

同步是指在多个线程并发访问共享数据时,保证共享数据在同一个时刻只被一条

(或者一些,使用信号量的时候)线程使用。

互斥是实现同步的一种手段,临界区(Critical Section)、互斥量(Mutex

和信号量(Semaphore)都是常见的互斥实现方式。

同步是目的,互斥是方法。

Java互斥同步的实现

Java互斥同步手段就是synchronized关键字,这是一种块结构(Block Structured

的同步语法。经过Javac编译后,会在同步块的前后分别形成monitorenter

monitorexit这两个字节码指令。这两个字节码指令都需要一个reference类型

的参数来指明要锁定和解锁的对象。

新的选择,java.util.concurrent.locks.Lock接口是JDK5提供一中全新的互斥同步手段。

重入锁(ReentrantLock)是Lock接口最常见的一种实现,与synchronized一样可重入的。

ReentrantLocksynchronized 多的功能:

  • 等待可中断:指当持有锁的线程长期不释放锁的时候,正在等待的线程可以选择放弃等待,

    改为处理其他事情,可中断特性对处理执行时间非常长的同步块很有帮助。

  • 公平锁:指多个线程在等待同一个锁时,必须按照申请锁的时间顺序来依次获得锁。

    synchronized中的锁是非公平的,ReentrantLock在默认情况下也是非公平的。不过使用

    了公平锁,将导致ReentrantLock的性能急剧下降,会明显影响吞吐量。

    为啥?

  • 锁绑定多个条件:是指一个ReentrantLock对象可以同时绑定多个Condition对象。

ReentrantLocksynchronized 的选择

JDK6加入了对synchronized锁的优化,synchronizedReentrantLock性能基本持平。

性能不是选择的决定因素。如果需要ReentrantLock新增加的功能,则选择ReentrantLock

优先使用synchronized的原因:

  • 足够清晰,足够简单

  • Lock需要确保在finally块中释放锁,否则一旦受同步保护的代码块中抛出异常,则有可能

    永远不会释放持有锁。synchronized的话则由Java虚拟机来确保即使出现异常,锁也会自动释放。

  • JDK5ReentrantLock性能领先synchronizedJDK5之后性能就持平了。而Java虚拟机更容易

    synchronized进行优化,因为Java虚拟机可以在线程和对象的元数据中记录synchronized

    锁的相关信息,而Lock的话虚拟机很难知道哪些锁对象是由特定线程锁持有的。