一、锁的种类和含义
Java的concurrent并发包中,存在两种类型的锁,即共享锁和排它锁,后者也叫做独占锁。
共享锁是指某一时刻锁可以被多个线程同时拥有,这些线程同时共享该锁。而排它锁则是指锁在某一时刻只能被一个线程拥有,任何想要获得该锁的线程,必须等待的锁的所有者释放后才可以。
二、ReentrantReadWriteLock的含义
ReentrantReadWriteLock是Java中的一种读写锁,它既不是完全的共享锁,也不是完全的排它锁。它实际上是一种混合形式的锁,既包含共享锁,同时也包含排它锁。
这么做是为了什么呢?我们知道,很多情况下有这样一种业务场景,即对于一块数据,或者一个对象,即存在需要读取的时候,也存在需要修改,即写入的时候。那么,如果对于这种应用场景,如果是只用共享锁,同一时刻,允许多个线程读取和写入数据,那么数据操作的原子性就无法得到保证,在多并发的情况下,数据往往就是紊乱的;如果是只用排它锁,即某一线程读取的时候,即不允许其它线程写入,也不允许其它线程读取,这样是能保证数据操作的原子性,得到正确的数据,那么性能也随之降低了。
所以,在兼顾数据操作的原子性和读写性能二者的情况下,一种同时融合共享锁和排它锁的混合锁的产生,就显得特别有意义了。这就是我们本文将要阐述的读写锁ReentrantReadWriteLock。
它在读取数据或对象的时候使用读锁,即一种对读共享同时读写排它的锁,允许多个线程同时读取数据,但是不允许其它线程修改数据;而在修改数据或对象时使用写锁,一种完全的排它锁,既不允许 其它线程读取数据,也不允许其他线程修改数据。这样,数据操作的原子性和性能同时得到了考虑。
三、ReentrantReadWriteLock的定义及实现
ReentrantReadWriteLock实现了Java中的ReadWriteLock接口。
四、ReentrantReadWriteLock的使用方式及代码示例
ReentrantReadWriteLock的使用方式如下:
首先,需要构造一个ReentrantReadWriteLock对象rrwl。代码如下:
// 构造ReentrantReadWriteLock对象rrwl private ReentrantReadWriteLock rrwl = new ReentrantReadWriteLock();其次,需要获取ReentrantReadWriteLock对象rrwl的读锁readLock和写锁writeLock。代码如下:
// 获取读锁readLock:可被多个读线程共享,但是会排斥所有的写线程 private Lock readLock = rrwl.readLock(); // 获取写锁writeLock:排斥所有的读线程和其它写线程 private Lock writeLock = rrwl.writeLock();然后,读锁的使用方法如下:
// 读锁的使用 public Object readObject() { Object object = null; // 利用读锁readLock获取读锁 readLock.lock(); try { // 此处为业务代码 object = new Object(); } finally { // 利用读锁readLock释放读锁 readLock.unlock(); } return object; }最后,写锁的使用方法如下:
// 写锁的使用 public void writeObject(Object object) { // 利用写锁writeLock获取写锁 writeLock.lock(); try { // 此处为业务代码 } finally { // 利用写锁writeLock释放写锁 writeLock.unlock(); } }