大纲:
- ReadWriteLock接口
- ReentrantReadWriteLock
- ReentrantReadWriteLock使用
一、ReadWriteLock
public interface ReadWriteLock { Lock readLock(); Lock writeLock(); }
- readLock获得读锁。
- writeLock获得写锁。
二、ReentrantReadWriteLock是ReadWriteLock的实现类
- ReentrantReadWriteLock内部维护了两个实现Lock接口的内部类ReadLock读锁,与WriteLock写锁。
- 仅写锁支持condition。
- 锁降级:写锁降级为读锁,获取写锁、获取读锁、释放写锁。
- 锁升级:不支持读锁升级为写锁。
- 线程间互斥关系:读读共享锁、读写独享锁、写写独享锁
public class Met { ReadWriteLock lock = new ReentrantReadWriteLock(); public void read(Thread thread){ try { lock.readLock().lock(); System.out.println(thread.getName()+"read lock"); for(int i =0;i<10;i++){ System.out.println(thread.getName()+":"+i); } } finally { System.out.println(Thread.currentThread().getName()+"read unlock"); lock.readLock().unlock(); } } public void write(Thread thread){ try { lock.writeLock().lock(); System.out.println(thread.getName()+"write lock"); for(int i =0;i<10;i++){ System.out.println(thread.getName()+":"+i); } } finally { System.out.println(Thread.currentThread().getName()+"write unlock"); lock.writeLock().unlock(); } } }
public class ReadRunnable implements Runnable { Met met; ReadRunnable(Met met){ this.met = met; } @Override public void run() { met.read(Thread.currentThread()); } }
public class WriteRunnable implements Runnable { Met met; WriteRunnable(Met met){ this.met = met; } @Override public void run() { met.write(Thread.currentThread()); } }
class TestReadWrite { public static void main(String[] args) { Met met = new Met(); ReadRunnable read = new ReadRunnable(met); WriteRunnable write = new WriteRunnable(met); Thread threadread0 = new Thread(read); Thread threadread1 = new Thread(read); Thread threadwrite0 = new Thread(write); threadread0.start(); threadread1.start(); threadwrite0.start(); } }
三、ReentrantReadWriteLock使用
官方demo:更新缓存后的锁降级,保持读锁。
public class CachedData { ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); String data = "未更新"; //缓存数据 volatile boolean isValid; //缓存数据是否有效 void processCachedData(){ readWriteLock.readLock().lock(); System.out.println(Thread.currentThread().getName()+"readLock.lock"); //校验缓存数据是否有效,若无效跟新data,有效直接使用 if(!isValid){ System.out.println(Thread.currentThread().getName()+"readLock.unlock"); readWriteLock.readLock().unlock(); readWriteLock.writeLock().lock(); System.out.println(Thread.currentThread().getName()+"writeLock.lock"); //再次校验 if(!isValid){ data = "已更新"; isValid = true; System.out.println(Thread.currentThread().getName()+">>>refresh data"); } //写锁降级为读锁:释放写锁前获取读锁 readWriteLock.readLock().lock(); System.out.println(Thread.currentThread().getName()+"readLock.lock"); System.out.println(Thread.currentThread().getName()+"writeLock.unlock"); //写锁被释放,读锁依旧 readWriteLock.writeLock().unlock(); } System.out.println(Thread.currentThread().getName()+">>>use data "+data); System.out.println(Thread.currentThread().getName()+"readLock.unlock"); readWriteLock.readLock().unlock(); } }
public class ReadWriteRunnable implements Runnable { CachedData task; public ReadWriteRunnable(CachedData task){ this.task = task; } @Override public void run() { task.processCachedData(); } }
class TestReadWrite { public static void main(String[] args) { CachedData task = new CachedData(); ReadWriteRunnable readWriteRunnable = new ReadWriteRunnable(task); new Thread(readWriteRunnable).start(); new Thread(readWriteRunnable).start(); new Thread(readWriteRunnable).start(); new Thread(readWriteRunnable).start(); new Thread(readWriteRunnable).start(); new Thread(readWriteRunnable).start(); } }