多執行緒學習----讀寫鎖的使用(十二)
阿新 • • 發佈:2018-11-17
讀寫鎖
讀寫鎖:分為讀鎖和寫鎖,多個讀鎖不互斥,讀鎖與寫鎖互斥,寫鎖和寫鎖互斥,這是由jvm自己控制的,你只要上好相應的鎖即可。如果你的程式碼只讀資料,可以很多人同時讀,但是不能同時寫,那就讓讀鎖;如果你的程式碼修改資料,只能有一個人在寫,且不能同時讀取,那就上寫鎖。總之,讀的時候上讀鎖,寫的時候上寫鎖!
讀寫鎖的應用:
假設開啟三個執行緒寫資料,三個執行緒讀資料(讀讀不互斥,讀寫互斥,寫寫互斥)
public class ReadWriteLockStudy { public static void main(String[] args) { ReadAndWrite raw = new ReadAndWrite(); for(int i = 0;i < 3;i++){ new Thread(new Runnable() { @Override public void run() { raw.get();//讀 } }).start(); new Thread(new Runnable() { @Override public void run() { raw.set(Math.random()*1000);//寫 } }).start(); } } } class ReadAndWrite{ private Object data = null; ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); public void get(){ readWriteLock.readLock().lock();; System.out.println(Thread.currentThread().getName()+" be ready to read"); try { Thread.sleep((long)Math.random()*1000); System.out.println(Thread.currentThread().getName()+" has read data:"+data); } catch (InterruptedException e) { e.printStackTrace(); }finally{ readWriteLock.readLock().unlock(); } } public void set(Object data){ readWriteLock.writeLock().lock(); try { System.out.println(Thread.currentThread().getName()+" be ready to write"); Thread.sleep((long)Math.random()*1000); this.data = data; System.out.println(Thread.currentThread().getName()+" has write data:"+this.data); } catch (InterruptedException e) { e.printStackTrace(); }finally{ readWriteLock.writeLock().unlock(); } } }
面試題:寫一個快取系統的虛擬碼
public class CacheDemoStudy { private Map<String,Object> cache = new HashMap<String,Object>(); public static void main(String[] args) { final CacheDemoStudy cacheDemoStudy = new CacheDemoStudy(); for(int i = 0;i < 5;i++){ new Thread(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName()+"拿到資料"+cacheDemoStudy.getData("dataKey")); } }).start(); } } private ReadWriteLock rwl = new ReentrantReadWriteLock(); public Object getData(String key){ rwl.readLock().lock(); try{ System.out.println(Thread.currentThread().getName()+"去拿資料"); if(cache.get(key) == null){ System.out.println(Thread.currentThread().getName()+"沒有拿到資料"); } if(cache.get(key) == null){ rwl.readLock().unlock(); rwl.writeLock().lock(); try{ if(cache.get(key) == null){ System.out.println(Thread.currentThread().getName()+"去寫資料"); cache.put("dataKey", "aaaaa"); } }finally{ rwl.writeLock().unlock(); } rwl.readLock().lock(); } }finally { rwl.readLock().unlock(); } return cache.get(key); } }
執行結果:
只去寫了一次資料