ReentrantReadWriteLock
当读操作远远高于写操作时,这时候使用读写锁
让读读
可以并发,提高性能。类似于数据库中select ... from ... lock in share mode
。
提供一个数据容器类
内部分别使用读锁保护数据的read()
,写锁保护数据的write()
方法。
@Slf4j(topic = "c.DataContainer")
class DataContainer {
private Object data;
private ReentrantReadWriteLock rw = new ReentrantReadWriteLock();
private ReentrantReadWriteLock.ReadLock r = rw.readLock();
private ReentrantReadWriteLock.WriteLock w = rw.writeLock();
public Object read() {
log.debug("获取读锁...");
r.lock();
try {
log.debug("读取");
Thread.sleep(1000);
return data;
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally {
log.debug("释放读锁...");
r.unlock();
}
}
public void write() {
log.debug("获取写锁...");
w.lock();
try {
log.debug("写入");
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally {
log.debug("释放写锁...");
w.unlock();
}
}
}
测试读锁-读锁
可以并发
public class TestReentrantReadWriteLock {
public static void main(String[] args) {
DataContainer dataContainer = new DataContainer();
new Thread(() -> {
dataContainer.read();
}, "t1").start();
new Thread(() -> {
dataContainer.read();
}, "t2").start();
}
}
输出结果,从这里可以看到 Thread-0 锁定期间,Thread-1 的读操作不受影响
17:41:10.773 [t2] - 获取读锁...
17:41:10.773 [t1] - 获取读锁...
17:41:10.774 [t2] - 读取
17:41:10.774 [t1] - 读取
17:41:11.776 [t1] - 释放读锁...
17:41:11.779 [t2] - 释放读锁...
测试读锁-写锁
相互阻塞
public class TestReentrantReadWriteLock {
public static void main(String[] args) throws InterruptedException {
DataContainer dataContainer = new DataContainer();
new Thread(() -> {
dataContainer.read();
}, "t1").start();
Thread.sleep(100);
new Thread(() -> {
dataContainer.write();
}, "t2").start();
}
}
输出结果
17:50:57.280 [t1] - 获取读锁...
17:50:57.281 [t1] - 读取
17:50:57.384 [t2] - 获取写锁...
17:50:58.287 [t1] - 释放读锁...
17:50:58.287 [t2] - 写入
17:50:59.291 [t2] - 释放写