ReentrantLock无论是“写/写”线程、“读/读”线程、“读/写”线程之间的工作都是互斥,同一 时间只有一个线程能进入同步区域。然而大多实际场景是“读/读”线程间并不存在互斥关系,只有"读/写"线程或"写/写"线程间的操作需要互斥的。
一个资源可以被多个读操作同时访问,而只能对一个写操作访问,但读和写两者不能同时进行。
从而提高读操作的吞吐量。
使用场景:对于读多写少的场景使用ReentrantReadWriteLock 性能会比ReentrantLock高出不少。
在多线程读时互不影响,不像ReentrantLock即使是多线程读也需要每个线程获取锁。不过任何一个线程在写的时候就和ReentrantLock类似,其他线程无论读还是写都必须获取锁。
需要注意的是同一个线程可以拥有 writeLock 与 readLock (但必须先获取 writeLock 再获取 readLock, 反过来进行获取会导致死锁)
默认构造方法为 非公平模式 ,开发者也可以通过指定构造方法传参数true设置为 公平模式。
读锁的条件直接调用ReentrantReadWriteLock的 newCondition 会直接exception public Condition newCondition() {
throw new UnsupportedOperationException();
}
- package com.lock;
-
- import org.apache.log4j.Logger;
-
- import java.util.concurrent.TimeUnit;
- import java.util.concurrent.locks.Lock;
- import java.util.concurrent.locks.ReentrantReadWriteLock;
-
- /**
- * 读写锁
- */
- public class LockTest6 {
- static Logger log = Logger.getLogger(LockTest6.class);
- static ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
- //读锁
- static Lock r = rwl.readLock();
- //写锁
- static Lock w = rwl.writeLock();
-
-
- public static void main(String[] args) throws InterruptedException {
-
- //读
- new Thread("读线程1 "){
- public void run(){
- log.debug("read1 获取 锁");
- r.lock();
- try {
- for (int i = 0; i < 10; i++) {
- m1(i);
- }
- }finally {
- r.unlock();
- }
- }
- }.start();
-
- //写
- new Thread("写线程--"){
- public void run(){
- log.debug("write 获取 锁");
- w.lock();
- try {
- for (int i = 0; i < 20; i++) {
- m1(i);
- }
- }finally {
- w.unlock();
- }
- }
- }.start();
-
-
- //读
- new Thread("读线程2"){
- public void run(){
- log.debug("read2 获取 锁");
- r.lock();
- try {
- for (int i = 0; i < 20; i++) {
- m1(i);
- }
- }finally {
- r.unlock();
- }
-
- }
- }.start();
-
- }
-
-
- public static void m1(int i){
- log.debug(Thread.currentThread().getName()+"执行任务 "+i);
- try {
- TimeUnit.SECONDS.sleep(1);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
-
- }
- }
1:两个读线程可以并发访问,而写线程只能独自访问(独占)
2:读写支持重入但是只支持降级不止升级