ReadWriteLock与synchronize的性能对比

来源:互联网 发布:淘宝店铺出售骗局 编辑:程序博客网 时间:2024/06/05 19:44

在JDK5之前,我们要解决并发所产生的问题使用的是synchronized修饰。但是,对象的方法中一旦加入synchronized修饰,则任何时刻只能有一个线程访问synchronized修饰的方法。假设有个数据对象拥有写方法与读方法,多线程环境中要想保证数据的安全,需对该对象的读写方法都要加入 synchronized同步块。这样任何线程在写入时,其它线程无法读取与改变数据;如果有线程在读取时,其他线程也无法读取或写入。这种方式在写入远大于读取时,问题不大,而当读取远远大于写入时,会造成性能瓶颈,因为此种情况下读取操作是可以同时进行的,而加锁操作限制了数据的并发读取。

为此,Java 5平台新增了java.util.concurrent包,该包包含了许多非常有用的多线程应用类,例如ReadWriteLock,这使得开发人员不必自己封装就可以直接使用这些健壮的多线程类。

ReadWriteLock是一种常见的多线程设计模式。当多个线程同时访问同一资源时,通常,并行读取是允许的,但是,任一时刻只允许最多一个线程写入,从而保证了读写操作的完整性。下图很好地说明了ReadWriteLock的读写并发模型:

       读            写

读     允许        不允许

写     不允许    不允许

当读线程远多于写线程时,使用ReadWriteLock来取代synchronized同步会显著地提高性能,因为大多数时候,并发的多个读线程不需要等待。

Java 5的ReadWriteLock接口仅定义了如何获取ReadLock和WriteLock的方法,对于具体的ReadWriteLock的实现模式并没有规定,例如,Read优先还是Write优先,是否允许在等待写锁的时候获取读锁,是否允许将一个写锁降级为读锁,等等。

Java 5自身提供的一个ReadWriteLock的实现是ReentrantReadWriteLock,该ReadWriteLock实现能满足绝大多数的多线程环境,有如下特点:

1、支持两种优先级模式,以时间顺序获取锁和以读、写交替优先获取锁的模式;

2、当获得了读锁或写锁后,还可重复获取读锁或写锁,即ReentrantLock;

3、获得写锁后还可获得读锁,但获得读锁后不可获得写锁;

4、支持将写锁降级为读锁,但反之不行;

5、支持在等待锁的过程中中断;

6、对写锁支持Condition(用于取代wait,notify和notifyAll);

7、支持锁的状态检测,但仅仅用于监控系统状态而并非同步控制;

例子详见think in java 中的ReadWriteList<T>