1. 程式人生 > >Java通過讀寫鎖模擬緩存池

Java通過讀寫鎖模擬緩存池

runnable 一個 nbsp 今天 ted pub 項目 時長 讀寫鎖

  • 緩存池在項目開發中時長用到,在查看了一下相關的資料,發現很多博客中對緩存池的實現有存在著一些漏洞,今天花了點時間梳理一下,用JDK1.5中並發包中的ReentrantReadWriteLock實現一個從緩存中獲取數據的例子。本人技術有限,如果讀者發現Bug,敬請指出。程序員不喜歡多說,直接上代碼
  • 代碼
 1 import java.util.HashMap;
 2 import java.util.Map;
 3 import java.util.concurrent.locks.ReadWriteLock;
 4 import java.util.concurrent.locks.ReentrantReadWriteLock;
5 6 /** 7 * @author yuguojin 8 */ 9 public class ThreadCaChe { 10 11 private static Map<String, Object> cacheMap = new HashMap<String, Object>(); 12 13 private static ReadWriteLock lock = new ReentrantReadWriteLock(); 14 15 public static void main(String[] args) { 16 17
for (int i = 0; i < 100; i++) { 18 new Thread(new Runnable() { 19 20 @Override 21 public void run() { 22 String obj = (String) get("TestKey"); 23 System.out.println(obj); 24 25 } 26 }).start();
27 28 } 29 30 } 31 32 public static Object get(String key) { 33 lock.readLock().lock(); // 先加讀鎖 34 Object value = null; 35 try { 36 value = cacheMap.get(key); 37 if (value == null) { // 若不存在cache中 38 39 // 讓線程sleep 1秒方便測試 40 try { 41 Thread.sleep(1000); 42 } catch (InterruptedException e) { 43 e.printStackTrace(); 44 } 45 46 lock.readLock().unlock(); // 若果value為空 則釋放掉讀鎖,讓該線程獲取寫鎖,而其他線程只能等待該寫鎖釋放,才能在進讀鎖 47 lock.writeLock().lock(); // 加寫鎖 48 49 value = cacheMap.get(key); 50 try { 51 if (value == null) { 52 value = "Cache Data";// 查詢數據庫 ,從DB中獲取數據 53 // 存入緩存中 54 cacheMap.put(key, value); 55 } 56 } finally { 57 lock.readLock().lock(); 58 lock.writeLock().unlock(); 59 } 60 } 61 62 } finally { 63 lock.readLock().unlock(); // 釋放第一次獲取的讀鎖 64 } 65 66 return value; 67 } 68 }
  • 代碼備註

1. 代碼中我使用了一個HashMap模擬緩存,在獲取cacheMap緩存中的數據時如果cacheMap中沒有存在該值得時候就涉及到從數據庫中同步數據到cacheMap中,這樣對於cacheMap就涉及到讀寫操作;

2. 當多個線程同時獲取同一個數據的時候就就涉及到線程安全和線程同步的問題;

  • 代碼中容易出現的問題

1. 代碼13行中的lock必須是屬性級別的變量,初級程序員容易把lock寫成方法變量(這樣就達不到lock的作用)

2. 代碼49行需要在讀取緩存數據不存在的時候,並且已經獲得讀鎖的時候還需要在驗證一次這個數據是否存在緩存中(解決高並發時多個線程同時凈增讀鎖是,後產生的多次數據庫查詢操作)

3. 鎖是占用資源的操作,最後必須把鎖釋放,所以使用的finally模塊釋放鎖

4. 代碼46/47和代碼57/58中釋放鎖和獲取鎖的順序是不可以改變的(因為)在java鎖機制中讀鎖是可以升級為寫鎖,然而寫鎖是不可以降級為讀鎖的,所以必須先釋放讀鎖在獲取寫鎖,不然會被鎖死

Java通過讀寫鎖模擬緩存池