ReadWriteLock 读写锁
读写操作分为三个情况:读-读,写-写,读-写,其中仅有读-读被读写锁允许
也就是说,一个线程读取数据时,其他线程也可读取,但不能写入(避免读脏数据);一个线程写入时,其他线程不可读取(避免读脏数据),也不可写入(避免数据错误)
综上所述,在读取操作庞大的情况下,选用读写锁可以极大程度上提高程序的性能
需要注意的是,读锁与写锁必须配套使用,否则无法达到预期效果
示例代码
public class Test {
private volatile Map<String ,Object> map = new HashMap<>();
ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
public void put(String key, Object value){
try {
//写锁 确保仅有一个线程在写入
readWriteLock.writeLock().lock();
System.out.println(Thread.currentThread().getName() + "开始写入 key=" + key);
map.put(key, value);
System.out.println(Thread.currentThread().getName() + "写入完毕");
} catch (Exception e) {
e.printStackTrace();
} finally {
//解锁
readWriteLock.writeLock().unlock();
}
}
public void read(String key){
try {
//读锁 确保读取时无法写入 但可读取(其他线程)
readWriteLock.readLock().lock();
System.out.println(Thread.currentThread().getName() + "开始读取 key=" + key);
Object o = map.get(key);
System.out.println(Thread.currentThread().getName() + "读取完毕 value=" + o);
} catch (Exception e) {
e.printStackTrace();
} finally {
//解锁
readWriteLock.readLock().unlock();
}
}
}
运行效果
可以看到,一个线程写入时,其他线程无法写入与读取;一个线程读取时,其他线程也可读取,但无法写入
为什么不直接使用Lock呢?
将上文示例代码中的ReadWriteLock替换为Lock后的运行效果:
可以看到,一个线程写入时,其他线程无法写入与读取,符合写锁要求;但一个线程读取时,其他线程也无法写入与读取,不符合读锁要求
读取数据时需要等待其他线程释放锁,在读取操作庞大的情况下会极大程度上影响程度的性能