读写锁
相比Java中的锁(Locks in Java)里Lock实现,读写锁更复杂一些。假设你的程序中涉及到对一些共享资源的读和写操作,且写操作没有读操作那么频繁。在没有写操作的时候,两个线程同时读一个资源没有任何问题,所以应该允许多个线程能在同时读取共享资源。但是如果有一个线程想去写这些共享资源,就不应该再有其它线程对该资源进行读或写(译者注:也就是说:读-读能共存,读-写不能共存,写-写不能共存)。这就需要一个读/写锁来解决这个问题。Java5在java.util.concurrent包中已经包含了读写锁。尽管如此,我们还是应该了解其实现背后的原理。
读 写 这种的 可以用wait notify 之前已经实现过了 读的时候不能写 写的时候不能做 保证共性的全局变量安全
下面,先来写个读写锁大家看看:
package com.toov5.readAndWriteLock; import java.util.HashMap; import java.util.Map; //读写锁 类似jvm内置缓存(把值存到jvm中) public class writeAndReadLock { private volatile Map<Object,Object> cache = new HashMap<>(); //写入元素 public void put(String key,String value){ try { Thread.sleep(500); System.out.println("写入"+key+value); cache.put(key, value); System.out.println("写入"+key+value+"结束"); } catch (InterruptedException e) { e.printStackTrace(); } } //读取元素 public String get(String key){ try { Thread.sleep(500); System.out.println("读取"+key); String result = cache.get(key).toString(); System.out.println("读取"+key+"结束"); return result; } catch (Exception e) { return null; } } public static void main(String[] args) { writeAndReadLock lock = new writeAndReadLock(); //写线程 Thread t1 = new Thread(new Runnable() { @Override public void run() { for(int i =0; i<10;i++){ lock.put("i", i+""); } } }); //读线程 Thread t2 = new Thread(new Runnable() { @Override public void run() { for(int i=0; i<10;i++){ lock.get(i+""); } } }); t1.start(); t2.start(); } }
结果:
如果两个方法都加上synchronize 那么读的时候 不能写 写的时候不能读
下面提供读写锁:
package com.toov5.readAndWriteLock; import java.util.HashMap; import java.util.Map; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock; import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; //读写锁 类似jvm内置缓存(把值存到jvm中) public class writeAndReadLock { private volatile Map<Object,Object> cache = new HashMap<>(); private ReentrantReadWriteLock wrl = new ReentrantReadWriteLock(); private WriteLock wirtelock=wrl.writeLock();//获取到写锁 private ReadLock readLock =wrl.readLock(); //获取到读锁 //写入元素 public void put(String key,String value){ try { wirtelock.lock(); Thread.sleep(500); System.out.println("写入"+key+value); cache.put(key, value); System.out.println("写入"+key+value+"结束"); } catch (InterruptedException e) { e.printStackTrace(); }finally { wirtelock.unlock(); } } //读取元素 public String get(String key){ try { readLock.lock(); Thread.sleep(500); System.out.println("读取"+key); String result = cache.get(key).toString(); System.out.println("读取"+key+"结束"); return result; } catch (Exception e) { return null; }finally{ readLock.unlock(); } } public static void main(String[] args) { writeAndReadLock lock = new writeAndReadLock(); //写线程 Thread t1 = new Thread(new Runnable() { @Override public void run() { for(int i =0; i<10;i++){ lock.put("i", i+""); } } }); //读线程 Thread t2 = new Thread(new Runnable() { @Override public void run() { for(int i=0; i<10;i++){ lock.get(i+""); } } }); t1.start(); t2.start(); } }
没有写完时候 是不能读的
看源码:
与之前的lock锁不一样之前是 reentrantlock,它有读和写两把锁
两个线程同时写,同时读是不可能的。不共存!
读读 可以 读写不可共存 写写不可以共存