Java5併發庫之鎖(二)——讀寫鎖技術的妙用

讀寫鎖:讀寫鎖分爲讀鎖和寫鎖,多個讀鎖不互斥,讀鎖與寫鎖互斥,寫鎖與寫鎖互斥,這是由JVM本身控制的,咱們只要上好相應的鎖便可。若是代碼是隻讀數據,能夠不少人同時讀,但不能同時寫,那就須要上讀鎖;若是代碼是修改數據,只能有一我的在寫,且不能在寫的時候讀,就須要上寫鎖。總之,讀的時候上讀鎖,寫的時候上寫鎖。java

  • 1- 1 一個讀寫鎖的例子
  •    
       
       
       
    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. public class CacheDemo { 
    7.     private Map<String, Object> cache = new HashMap<String, Object>(); 
    8.     public static void main(String[] args) { 
    9.  
    10.     } 
    11.     private ReadWriteLock rwl = new ReentrantReadWriteLock(); 
    12.     public  Object getData(String key){ 
    13.         rwl.readLock().lock(); 
    14.         Object value = null
    15.         try
    16.             value = cache.get(key); 
    17.             if(value == null){ 
    18.                 rwl.readLock().unlock(); 
    19.                 rwl.writeLock().lock(); 
    20.                 try
    21.                     if(value==null){ 
    22.                         value = "aaaa";//實際失去queryDB(); 
    23.                     } 
    24.                 }finally
    25.                     rwl.writeLock().unlock(); 
    26.                 } 
    27.                 rwl.readLock().lock(); 
    28.             } 
    29.         }finally
    30.             rwl.readLock().unlock(); 
    31.         } 
    32.         return value; 
    33.     } 

程序運行的結果:面試

從運行結果能夠看到,當一個線程寫的時候,其它的線程不容許寫;而讀的時候,容許多個線程同時讀,且讀到的數據是一致的。數據庫

在Hibernate中會有代碼1-2 這樣的代碼:緩存

  • 代碼1-2
  
  
  
  
  1. User user = session.load(id,User.class); 
  • 代碼1-3
  
  
  
  
  1. User user = session.get(id,User.class); 

那麼代碼1-2 與 1-3 有什麼區別呢?session

代碼1-2 ,無論數據庫中有沒有記錄,它都返回一個user對象,它是一個代理(是user的子類,能夠被當作user用),是一個假的,不是一個真正的user對象。以下圖:ide

代碼1-3 ,是直接到數據庫中把對象給「抓」出來,若是沒有「抓」到,返回的值是NULL(空)。看看下面的這道面試題:spa

  • 一個緩存系統(能夠裝不少的對象)的例子
  •    
       
       
       
    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. public class CacheDemo { 
    7.     private Map<String, Object> cache = new HashMap<String, Object>();//定義緩存 
    8.     public static void main(String[] args) { 
    9.  
    10.     } 
    11.     private ReadWriteLock rwl = new ReentrantReadWriteLock();//定義一個讀寫鎖 
    12.     /* 
    13.        取數據的方法,檢查內部是否有key這個數據,若是有,直接傳遞給程序;沒有,去數據庫查, 
    14.        查到以後存到緩存的內存中。  下次,再有程序找該數據時,直接將緩存中的數據傳給程序,不須要訪問數據庫 
    15.      */ 
    16.     public  Object getData(String key){ 
    17.         rwl.readLock().lock();//首先都上讀鎖*(均可以讀),加鎖,實現多個線程的訪問 
    18.         Object value = null;//注意:在try{}catch(){}中不能定義變量 
    19.         try
    20.             value = cache.get(key);//在cache中取數據 
    21.             if(value == null){ 
    22.                 rwl.readLock().unlock();//釋放讀鎖**(注意*的對應關係) 
    23.                 rwl.writeLock().lock();//上寫鎖*** 
    24.                 try
    25.                     if(value==null){//當其它的線程檢查不爲空,就不用再寫 
    26.                         value = "aaaa";//實際是去queryDB();   
    27.                     } 
    28.                 }finally
    29.                     rwl.writeLock().unlock();//釋放寫鎖*** 
    30.                 } 
    31.                 rwl.readLock().lock();//恢復讀鎖** 
    32.             } 
    33.         }finally
    34.             rwl.readLock().unlock();//釋放讀鎖* 
    35.         } 
    36.         return value; 
    37.     } 

注意代碼線程

  
  
  
  
  1. if(value==null){//當其它的線程檢查不爲空,就不用再寫  
  2.                        value = "aaaa";//實際是去queryDB();    
  3. }  

當其它的線程檢查緩存中有數據時,就再也不進行寫的操做。代理

相關文章
相關標籤/搜索