一、什么是读写锁
读写锁是JDK1.5提供的一个工具锁,适用于读多写少的场景,将读写分离,从而提高并发性。
二、读写锁的特点
- 读锁是共享锁,写锁是排他锁,读锁和写锁不能同时存在;
- 读锁不能升级为写锁;
- 写锁可以降级为读锁;
三、代码演示
import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; //定义缓存 public class MyCache { private volatile Map<String, Object> cache = new HashMap<>(); //读写锁 private final ReadWriteLock rwLock = new ReentrantReadWriteLock(); //获取写锁 private final Lock wlock = rwLock.writeLock(); //获取读锁 private final Lock rLock = rwLock.readLock(); // 写数据 public void put(String key, Object value) throws InterruptedException { //加锁 wlock.lock(); try { System.out.println(Thread.currentThread().getName() + ",写入数据:" + key); TimeUnit.SECONDS.sleep(2); cache.put(key, value); System.out.println(Thread.currentThread().getName() + ",写入数据完成:" + key); } finally { //释放锁 wlock.unlock(); } } //读数据 public Object get(String key) throws InterruptedException { Object res = cache.get(key); //加锁 rLock.lock(); try { System.out.println(Thread.currentThread().getName() + ",读数据:" + key); TimeUnit.SECONDS.sleep(2); System.out.println(Thread.currentThread().getName() + ",读数据完成:" + key); } finally { //释放锁 rLock.unlock(); return res; } } }
1、共享读
public static void main(String[] args) { MyCache cache=new MyCache(); for (int i = 0; i < 5; i++) { String key=String.valueOf(i+1); new Thread(()->{ try { cache.get(key); } catch (InterruptedException e) { e.printStackTrace(); } },"read-"+key).start(); } }
2、独占写
public static void main(String[] args) { MyCache cache=new MyCache(); for (int i = 0; i < 5; i++) { String key=String.valueOf(i+1); new Thread(()->{ String str = UUID.randomUUID().toString(); try { cache.put(key,str.substring(4,10)); } catch (InterruptedException e) { e.printStackTrace(); } },"wirte-"+key).start(); } }
3、写锁降级为读锁,可以写读
public static void main(String[] args) { //读写锁 final ReadWriteLock rwLock = new ReentrantReadWriteLock(); //获取写锁 final Lock wlock = rwLock.writeLock(); //获取读锁 final Lock rLock = rwLock.readLock(); //加锁 wlock.lock(); System.out.println("写锁开始工作"); rLock.lock(); System.out.println("读锁开始工作"); wlock.unlock(); rLock.unlock(); }
4、锁升级,不可以读写
public static void main(String[] args) { //读写锁 final ReadWriteLock rwLock = new ReentrantReadWriteLock(); //获取写锁 final Lock wlock = rwLock.writeLock(); //获取读锁 final Lock rLock = rwLock.readLock(); //加锁 rLock.lock(); System.out.println("读锁开始工作"); wlock.lock(); System.out.println("写锁开始工作"); rLock.unlock(); wlock.unlock(); }
ReentrantReadWriteLock适合于读多写少的场合,可以提高并发效率,而ReentrantLock适合普通场合