并发工具:ReadWriteLock和ReentrantReadWriteLock

对共享资源的访问一般包括两种类型的动作,读和写(修改、删除等会引起资源发生变化的动作),当多个线程同时对某个共享资源进行读取操作时,并不会引起共享资源数据不一致情况的发生(如表3-2所示),因此这个时候如果仍旧让资源的访问互斥,就会显得有些不合情理了,Doug Lea在JDK 1.5版本引入了读写锁类,旨在允许某个特定时刻多线程并发读取共享资源,提高系统性能和访问吞吐量。

可参考: 多线程设计模式: 读写锁分离设计模式

1 读写锁的基本使用方法

使用的过程中需要分别派生出“读锁”和“写锁”,在进行共享资源读取操作时,需要使用读锁进行数据同步,在对共享资源进行写操作时,需要使用写锁进行数据一致性的保护

public class ReentrantReadWriteLockDemo1 {
    // 定义读写锁
    ReadWriteLock lock = new
            ReentrantReadWriteLock();
    // 读锁
    Lock readLock = lock.readLock();
    // 写锁
    Lock writeLock = lock.writeLock();
    // 共享数据
    private final LinkedList<String> list = new LinkedList<>();


    /**
     * 添加数据
     */
    public void add(String data) {
        writeLock.lock();
        try {
            list.addLast(data);
        } finally {
            writeLock.unlock();
        }
    }

    /**
     * 删除数据
     *
     * @return
     */
    public String take() {
        writeLock.lock();
        try {
            return list.removeFirst();
        } finally {
            writeLock.unlock();
        }
    }

    /**
     * 使用读锁进行数据同步
     */
    public String get(int index) {
        readLock.lock();
        try {
            return list.get(index);
        } finally {
            readLock.unlock();
        }
    }
    
}

  1. 首先创建了一个ReentrantReadWriteLock锁,然后根据该锁分别创建了读锁和写锁。
  2. 读锁和写锁都是Lock接口的实现,因此具有Lock接口所定义的所有方法,比如lock()、unlock()等方法。
  3. 若某个线程获取了写锁进行数据写操作,那么此时其他线程对共享资源的读写操作都会被阻塞直到锁被释放。
  4. 若某个线程获取了读锁进行数据读操作,那么此时其他线程对共享资源的写操作会进入阻塞直到锁被释放,但如果是其他线程对共享资源进行读操作则不会被阻塞。

2 读写锁的方法

ReadWriteLock接口只有两个方法用于创建读锁和写锁,ReentrantReadWriteLock实现自ReadWriteLock接口并且提供了一些ReadWriteLock监控查询方法

public interface ReadWriteLock {
    /**
     * Returns the lock used for reading.
     *
     * @return the lock used for reading
     */
    Lock readLock();

    /**
     * Returns the lock used for writing.
     *
     * @return the lock used for writing
     */
    Lock writeLock();
}

ReentrantReadWriteLock实现了ReadWriteLock

public class ReentrantReadWriteLock
        implements ReadWriteLock, java.io.Serializable {
    
    /** Inner class providing readlock */
    private final ReentrantReadWriteLock.ReadLock readerLock;
    /** Inner class providing writelock */
    private final ReentrantReadWriteLock.WriteLock writerLock;
    public ReentrantReadWriteLock.WriteLock writeLock() {
    	 return writerLock; 
    }
    public ReentrantReadWriteLock.ReadLock  readLock()  { 
    	return readerLock; 
    }
	// 实现了Lock接口,所以具有Lock接口的所有能力
	public static class ReadLock implements Lock, java.io.Serializable{
	}
	// 实现了Lock接口,所以具有Lock接口的所有能力
	public static class WriteLock implements Lock, java.io.Serializable{
	}
}

ReentrantReadWriteLock、ReadLock以及WriteLock的方法与ReentrantLock十分相似,这里不做介绍,可参考:

并发工具:Lock和ReentrantLock

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值