JAVA多线程并发--使用ReadWriteLock实现读写锁
2021-06-24 本文已影响0人
砌月东谷
JUC提供了专门的读写锁ReadWriteLock,可以分别用于对读操作或者写操作进行加锁,在源码中主要定义了两个接口,分别是readLock和writeLock:
readLock 读锁
加了读锁的资源,可以在没有写锁的时候被多个线程共享,换句话说,如果线程1获取了读锁,那么此时可能存在两种状态:
- 如果2线程要申请写锁,则2线程会一直等待1线程释放读锁
- 如果2线程要申请读锁,则2线程可以直接读取资源,也就是说读锁是共享锁
writeLock 写锁
写锁是独占锁,加了写锁的资源,不能再被其他线程读或者写,如果1线程已经获取了写锁,那么无论2线程要申请写锁或者读锁,都必须等待1线程释放写锁
第一种情况,当1线程获取了读锁后,2线程也可以获取读锁
/**
* 第一种情况,当1线程获取了读锁后,2线程也可以获取读锁
*/
//读写锁的实现类
ReentrantReadWriteLock reentrantReadWriteLock=new ReentrantReadWriteLock();
new Thread(()->{
reentrantReadWriteLock.readLock().lock();
for(int i=0;i<100000;i++){
System.out.println(Thread.currentThread().getName()+"正在进行读操作");
}
System.out.println(Thread.currentThread().getName()+"读操作完毕");
reentrantReadWriteLock.readLock().unlock();
}).start();
new Thread(()->{
reentrantReadWriteLock.readLock().lock();
for(int i=0;i<100000;i++){
System.out.println(Thread.currentThread().getName()+"正在进行读操作");
}
System.out.println(Thread.currentThread().getName()+"读操作完毕");
reentrantReadWriteLock.readLock().unlock();
}).start();
运行截图:
image-20210624100526881.png
可以看到线程1和线程2交替执行
第二种情况 当线程1获取了读锁后,线程2获取写锁
//读写锁的实现类
ReentrantReadWriteLock reentrantReadWriteLock=new ReentrantReadWriteLock();
new Thread(()->{
reentrantReadWriteLock.readLock().lock();
for(int i=0;i<100000;i++){
System.out.println(Thread.currentThread().getName()+"正在进行读操作");
}
System.out.println(Thread.currentThread().getName()+"读操作完毕");
reentrantReadWriteLock.readLock().unlock();
}).start();
new Thread(()->{
reentrantReadWriteLock.writeLock().lock();
for(int i=0;i<100000;i++){
System.out.println(Thread.currentThread().getName()+"正在进行写操作");
}
System.out.println(Thread.currentThread().getName()+"写操作完毕");
reentrantReadWriteLock.writeLock().unlock();
}).start();
运行截图:
image-20210624100830746.png
线程1获取了读锁,线程2尝试获取写锁,需要等线程1释放读锁后
第三种情况 当线程1获取了写锁,线程2获取写锁或者读锁读都需要等待线程1释放写锁
/**
* 第三种情况,当线程1先获取写锁,不管线程2获取读锁还是写锁都要先等线程1释放写锁
*/
//读写锁的实现类
ReentrantReadWriteLock reentrantReadWriteLock=new ReentrantReadWriteLock();
new Thread(()->{
reentrantReadWriteLock.writeLock().lock();
for(int i=0;i<100;i++){
System.out.println(Thread.currentThread().getName()+"正在进行写操作");
}
System.out.println(Thread.currentThread().getName()+"写操作完毕");
reentrantReadWriteLock.writeLock().unlock();
}).start();
new Thread(()->{
reentrantReadWriteLock.readLock().lock();
for(int i=0;i<100;i++){
System.out.println(Thread.currentThread().getName()+"正在进行读操作");
}
System.out.println(Thread.currentThread().getName()+"读操作完毕");
reentrantReadWriteLock.readLock().unlock();
}).start();
运行截图:
image-20210624101225906.png