读写锁:ReentrantReadWriteLock
读操作共享资源,写操作独占资源
防止在写操作的过程中被其他线程读取(读取不完整)
缺点:可能造成读的饥饿问题,一直读,没有写
//资源类 class MyCache{ //创建资源集合 private volatile Map<String, Object> map = new HashMap<>(); private ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock(); //写数据 public void put(String key,Object value){ //添加写锁 readWriteLock.writeLock().lock(); try { System.out.println(Thread.currentThread().getName()+":正在做写操作"+key); TimeUnit.MICROSECONDS.sleep(300); //等待300毫秒 } catch (InterruptedException e) { e.printStackTrace(); }finally { //解锁 readWriteLock.writeLock().unlock(); } //放数据 map.put(key, value); System.out.println(Thread.currentThread().getName()+"写完了"+key); } //取数据 public Object get(Object key){ //添加读锁 readWriteLock.readLock().lock(); Object result = null; try { System.out.println(Thread.currentThread().getName()+":正在做读操作"+key); TimeUnit.MICROSECONDS.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); }finally { //解锁 readWriteLock.readLock().unlock(); } //取数据 result = map.get(key); System.out.println(Thread.currentThread().getName()+"取完了"+key); return result; } } public class ReadWriteLockDemo { public static void main(String[] args) { MyCache myCache = new MyCache(); //创建多个线程放数据 for (int i = 1; i <=5 ; i++) { final int num = i; new Thread(()->{ myCache.put(num+"", num+""); },String.valueOf(i)).start(); } //创建多个线程取数据 for (int i = 1; i <=5; i++) { final int num = i; new Thread(()->{ myCache.get(num+""); },String.valueOf(i)).start(); } } }
降写锁降级为读锁
写锁是可以降级为读锁的;写锁只有一个,当写锁降级为读锁时,所有的都是读。
//写锁降级为读锁 public class Demo1 { public void downgrade(){ //可重入读写锁对象 ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock(); ReentrantReadWriteLock.ReadLock readLock = rwLock.readLock();//读锁 ReentrantReadWriteLock.WriteLock writeLock = rwLock.writeLock();//写锁 System.out.println(Thread.currentThread().getName()+"尝试获取写锁"); writeLock.lock(); try{ System.out.println(Thread.currentThread().getName()+"获取到了写锁"); System.out.println(Thread.currentThread().getName()+"降级获取读锁"); readLock.lock(); //降级为读锁 try{ }finally { readLock.unlock(); } }finally { writeLock.unlock(); } } public static void main(String[] args) { Demo1 demo1 = new Demo1(); new Thread(()->demo1.downgrade(),"线程1").start(); new Thread(()->demo1.downgrade(),"线程2").start(); } }