并发编程系列之ReadWriteLock使用
Posted smileNicky
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了并发编程系列之ReadWriteLock使用相关的知识,希望对你有一定的参考价值。
并发编程系列之ReadWriteLock使用
1、什么是ReadWriteLock?
ReadWriteLock是jdk的juc包中提供的读写锁api,维护一对关联的读锁、写锁,读锁可以被多个读线程共享,写锁排他。
2、为什么需要ReadWriteLock?
之前我们喜欢使用ReentrantLock,重入锁,既然提供了ReentrantLock这个api,jdk官方又推出ReadWriteLock,相对ReentrantLock来说,ReadWriteLock是比较省资源的,ReentrantLock虽然也可以保证线程安全,但是比较耗资源的,比如在所有线程都是读锁的情况,这种情况就是线程安全的,就不需要做线程安全控制,直接保证线程并行执行就行,但是ReentrantLock不能做到,所以ReadWriteLock根据一系列规则保证了线程安全也保证了执行效率。
3、ReadWriteLock的常用API
ReadWriteLock在jdk8的juc包里有两个实现类:
ReentrantReadWriteLock的主要方法:
4、读写锁的获取规则
- 如果一个线程已经占用了读锁,其他线程想要申请读锁,是可以申请成功的
- 如果一个线程已经占用了读锁,其他线程想要申请写锁,是不可以申请成功的
- 如果一个线程已经占用了写锁,其他线程想要申请读锁还是写锁,都是不可以申请成功的
总结起来就是:读读共享、其他都互斥(写写互斥、读写互斥、写读互斥)
5、ReadWriteLock的适用场景
知道了ReadWriteLock的特效之后,我们知道相比于 ReentrantLock 适用于一般场合,ReadWriteLock 适用于读多写少的情况,合理使用可以进一步提高并发效率
6、ReadWriteLock的例子
例子,使用ReentrantReadWriteLock
创建读锁和写锁
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class ReadWriteLockExample
private static ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock();
private static ReentrantReadWriteLock.ReadLock readLock = reentrantReadWriteLock.readLock();
private static ReentrantReadWriteLock.WriteLock writeLock = reentrantReadWriteLock.writeLock();
public static void read()
readLock.lock();
try
System.out.println(Thread.currentThread().getName()+"得到了读锁");
Thread.sleep(500);
catch (InterruptedException e)
e.printStackTrace();
finally
System.out.println(Thread.currentThread().getName()+"释放读锁");
readLock.unlock();
public static void write()
writeLock.lock();
try
System.out.println(Thread.currentThread().getName() + "得到了写锁");
Thread.sleep(500);
catch (InterruptedException e)
e.printStackTrace();
finally
System.out.println(Thread.currentThread().getName() +"释放写锁");
writeLock.unlock();
public static void main(String[] args)
new Thread(() -> read()).start();
new Thread(() -> read()).start();
new Thread(() -> read()).start();
new Thread(() -> write()).start();
new Thread(() -> write()).start();
new Thread(() -> write()).start();
控制台打印,从打印结果可以看出,读锁可以同时被多个线程获得的,一个线程获取到读锁之后,另外一个线程又获取来了,而写锁必须等线程释放之后,才可以被其他线程获取,所以读锁共享,写锁排他
Thread-0得到了读锁
Thread-1得到了读锁
Thread-1释放读锁
Thread-0释放读锁
Thread-3得到了写锁
Thread-3释放写锁
Thread-2得到了读锁
Thread-2释放读锁
Thread-4得到了写锁
Thread-4释放写锁
Thread-5得到了写锁
Thread-5释放写锁
锁降级:指的是写锁降级成为读锁。把持住当前写锁的同时,再获取读锁,随后释放写锁的过程。写锁是线程独占的,读锁是共享的。所以写锁降级为读锁是降级。读锁升级为写锁不能实现。例子来自网上,稍作修改:
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class ReadWriteLockCachedDataExample
class Data
class RWDictionary
private final Map<String, Data> map = new ConcurrentHashMap<>();
private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
private final Lock rLock = readWriteLock.readLock();
private final Lock wLock = readWriteLock.writeLock();
public Data get(String key)
rLock.lock();
try
return map.get(key);
finally
rLock.unlock();
public Data put(String key , Data value)
wLock.lock();
try
return map.put(key , value);
finally
wLock.unlock();
public String[] allKeys()
rLock.lock();
try
return (String[]) map.keySet().toArray();
finally
rLock.unlock();
public void clear()
wLock.lock();
try
map.clear();
finally
wLock.unlock();
class CachedData
Object data;
volatile boolean cacheValid;
final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
void processCachedData()
rwl.readLock().lock();
if (!cacheValid)
// Must release read lock before acquiring write lock
rwl.readLock().unlock();
rwl.writeLock().lock();
try
// Recheck state because another thread might have
// acquired write lock and changed state before we did.
if (!cacheValid)
data = getData();
cacheValid = true;
// 【降级】Downgrade by acquiring read lock before releasing write lock
rwl.readLock().lock();
finally
rwl.writeLock().unlock();
try
use(data);
finally
rwl.readLock().unlock();
private Object getData()
return null;
void use(Object data)
附录参考资料
以上是关于并发编程系列之ReadWriteLock使用的主要内容,如果未能解决你的问题,请参考以下文章
Java——多线程高并发系列之ReadWriteLock读写锁
Java——多线程高并发系列之ReadWriteLock读写锁