ReetrantWriteReadLock使用
转载:https://blog.csdn.net/qq_41723615/article/details/88776152
一、读写锁简介
现实中有这样一种场景:对共享资源有读和写的操作,且写操作没有读操作那么频繁。在没有写操作的时候,多个线程同时读一个资源没有任何问题,所以应该允许多个线程同时读取共享资源;但是如果一个线程想去写这些共享资源,就不应该允许其他线程对该资源进行读和写的操作了。
针对这种场景,JAVA的并发包提供了读写锁ReentrantReadWriteLock,它表示两个锁,一个是读操作相关的锁,称为共享锁;一个是写相关的锁,称为排他锁。
线程进入读锁的前提条件:
- 没有其他线程的写锁,
- 没有写请求或者有写请求,但调用线程和持有锁的线程是同一个。
线程进入写锁的前提条件:
-
没有其他线程的读锁
-
没有其他线程的写锁
而读写锁有以下三个重要的特性:
-
公平选择性:支持非公平(默认)和公平的锁获取方式,吞吐量还是非公平优于公平。
-
重进入:读锁和写锁都支持线程重进入。
-
锁降级:遵循获取写锁、获取读锁再释放写锁的次序,写锁能够降级成为读锁。
ReentrantReadWriteLock的使用:
- 读读共享
- 写写互斥
- 读写互斥
- 写读互斥
public class ThreadA extends Thread {
private Service service;
// 线程A
public ThreadA(Service service){
super();
this.service=service;
}
@Override
public void run(){
service.read();
}
}
public class ThreadB extends Thread {
private Service service;
//线程B
public ThreadB(Service service){
super();
this.service=service;
}
@Override
public void run(){
service.write();
}
}
通过修改ThreadA和ThreadB类,run方法中调用的read/write方法,启动Service类测ReetrantWriteReadLock读写互斥情况;
public class Service {
private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
//读锁
private final Lock r = lock.readLock();
//写锁
private final Lock w = lock.writeLock();
//读锁
public void read() {
try {
try {
//启动读锁
lock.readLock().lock();
System.out.println("获取读锁" + Thread.currentThread().getName()
+ " " +System.currentTimeMillis());
Thread.sleep(10000);
} finally {
//关闭读锁
lock.readLock().unlock();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//写锁
public void write() {
try {
try {
//启动写锁
lock.writeLock().lock();
System.out.println("获取写锁" + Thread.currentThread().getName()
+ " " +System.currentTimeMillis());
Thread.sleep(10000);
} finally {
//关闭写锁
lock.writeLock().unlock();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args)throws InterruptedException {
Service service = new Service();
ThreadA a = new ThreadA(service);
a.setName("A");
a.start();
Thread.sleep(1000);
ThreadB b = new ThreadB(service);
b.setName("B");
b.start();
}
}
读写,写读,写写都是互斥的,读读是异步的,非互斥的。