在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>
本文深入探讨了Java5平台引入的ReadWriteLock接口及其实现方式,通过比较synchronized关键字与ReadWriteLock在多线程环境下的性能表现,详细解释了ReadWriteLock如何在读多写少的场景下显著提升程序性能。文中还具体介绍了Java5自身提供的ReentrantReadWriteLock实现的特点,包括支持的优先级模式、可重复获取锁、写锁与读锁的转换等功能,以及如何在实际应用中灵活使用这些特性来优化多线程程序的并发控制。
9万+

被折叠的 条评论
为什么被折叠?



