9.java鎖之讀寫鎖程式碼驗證
阿新 • • 發佈:2022-04-12
1.實現一個讀寫快取的操作,假設開始沒有加鎖的時候,會出現什麼情況
import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; class MyCache { private volatile Map<String, Object> map = new HashMap<>(); public void put(String key, Object value) { System.out.println(Thread.currentThread().getName()+ "\t 正在寫入:" + key); try { // 模擬網路擁堵,延遲0.3秒 TimeUnit.MILLISECONDS.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); } map.put(key, value); System.out.println(Thread.currentThread().getName() + "\t 寫入完成"); }public void get(String key) { System.out.println(Thread.currentThread().getName() + "\t 正在讀取:"); try { // 模擬網路擁堵,延遲0.3秒 TimeUnit.MILLISECONDS.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); } Object value = map.get(key); System.out.println(Thread.currentThread().getName()+ "\t 讀取完成:" + value); } } public class ReadWriteWithoutLockDemo { public static void main(String[] args) { MyCache myCache = new MyCache(); // 執行緒操作資源類,5個執行緒寫 for (int i = 0; i < 5; i++) { final int tempInt = i; new Thread(() -> { myCache.put(tempInt + "", tempInt + ""); }, String.valueOf(i)).start(); } // 執行緒操作資源類, 5個執行緒讀 for (int i = 0; i < 5; i++) { final int tempInt = i; new Thread(() -> { myCache.get(tempInt + ""); }, String.valueOf(i)).start(); } } }
2.執行結果
0 正在寫入:0 1 正在寫入:1 3 正在寫入:3 2 正在寫入:2 4 正在寫入:4 0 正在讀取: 1 正在讀取: 2 正在讀取: 4 正在讀取: 3 正在讀取: 1 寫入完成 4 寫入完成 0 寫入完成 2 寫入完成 3 寫入完成 3 讀取完成:3 0 讀取完成:0 2 讀取完成:2 1 讀取完成:null 4 讀取完成:null
3.看到有些執行緒讀取到null,可用ReentrantReadWriteLock解決
package com.mydemo; import java.util.HashMap; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantReadWriteLock; public class ReadWriteWithoutLockDemo { public static void main(String[] args) { MyCache myCache = new MyCache(); for (int i = 0; i < 5; i++) { final int i1=i; new Thread(()->{ myCache.put(i1+"",i1+""); },String.valueOf(i)).start(); } for (int i = 0; i < 5; i++) { final int i1=i; new Thread(()->{ myCache.get(i1+""); },String.valueOf(i)).start(); } } } class MyCache{ private volatile HashMap<String,String> map=new HashMap<>(); ReentrantReadWriteLock readWriteLock=new ReentrantReadWriteLock(); public void put(String key,String value){ readWriteLock.writeLock().lock(); System.out.println(Thread.currentThread().getName()+"\t 正在寫入"+key); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } map.put(key,value); System.out.println(Thread.currentThread().getName()+"\t 寫入完畢"+key); readWriteLock.writeLock().unlock(); } public void get(String key){ readWriteLock.readLock().lock(); System.out.println(Thread.currentThread().getName()+"\t正在讀取:"); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } String s = map.get(key); System.out.println(Thread.currentThread().getName()+"\t讀取完"+s); readWriteLock.readLock().unlock(); } }
4.執行結果
1 正在寫入1 1 寫入完畢1 0 正在寫入0 0 寫入完畢0 2 正在寫入2 2 寫入完畢2 3 正在寫入3 3 寫入完畢3 4 正在寫入4 4 寫入完畢4 0 正在讀取: 1 正在讀取: 2 正在讀取: 3 正在讀取: 4 正在讀取: 4 讀取完4 3 讀取完3 2 讀取完2 1 讀取完1 0 讀取完0
對ReentrantReadWriteLock其讀鎖是共享鎖,其寫鎖是獨佔鎖。