轉寄 :java線程:互斥鎖與讀寫鎖

來源:互聯網
上載者:User

標籤:

原文連結:http://coolxing.iteye.com/blog/1236909

 

兩種互斥鎖機制:

1、synchronized

2、ReentrantLock

ReentrantLock是jdk5的新特性,採用ReentrantLock可以完全替代替換synchronized傳統的鎖機制,而且採用ReentrantLock的方式更加物件導向,也更加靈活,網上有很多關於對比兩者鎖方式的文章,這裡就不多口舌了,大家baidu、google一下就水落石出了。在本部落格中也寫關於這兩種鎖方式實現的經典例子《生產者消費者》。

synchronized方式:《java線程:三種方式實現生產者消費者問題_1》

ReentranLock方式:《java線程:三種方式實現生產者消費者問題_2》

 

關於讀寫鎖,用語言解釋不如直接用代碼詮釋,以下通過兩個例子講述讀寫鎖以及讀寫鎖的使用:

例子1:

[java] view plaincopy 
  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 amber2012 
  8.  *  
  9.  * 讀寫鎖:ReadWriteLock 
  10.  *  
  11.  * 在多線程的環境下,對同一份資料進行讀寫,會涉及到安全執行緒的問題。比如在一個線程讀取資料的時候,另外一個線程在 
  12.  * 寫資料,而導致前後資料的不一致性;一個線程在寫資料的時候,另一個線程也在寫,同樣也會導致線程前後看到的資料的 
  13.  * 不一致性。 
  14.  *  
  15.  * 這時候可以在讀寫方法中加入互斥鎖,任何時候只能允許一個線程的一個讀或寫操作,而不允許其他線程的讀或寫操作,這 
  16.  * 樣是可以解決這樣以上的問題,但是效率卻大打折扣了。因為在真實的業務情境中,一份資料,讀取資料的操作次數通常高 
  17.  * 於寫入資料的操作,而線程與線程間的讀讀操作是不涉及到安全執行緒的問題,沒有必要加入互斥鎖,只要在讀-寫,寫-寫期 
  18.  * 間上鎖就行了。 
  19.  *  
  20.  * 對於這種情況,讀寫鎖則最好的解決方案! 
  21.  *  
  22.  * 讀寫鎖的機制: 
  23.  *      "讀-讀"不互斥 
  24.  *      "讀-寫"互斥 
  25.  *      "寫-寫"互斥 
  26.  *  
  27.  * 即在任何時候必須保證: 
  28.  *      只有一個線程在寫入; 
  29.  *      線程正在讀取的時候,寫入操作等待; 
  30.  *      線程正在寫入的時候,其他線程的寫入操作和讀取操作都要等待; 
  31.  *  
  32.  * 以下是一個緩衝類:用於示範讀寫鎖的操作:重入、降級 
  33.  */  
  34. public class CachedData {  
  35.       
  36.     // 緩衝都應該是單例的,在這裡用單例模式設計:  
  37.     private static CachedData cachedData = new CachedData();  
  38.     private final ReadWriteLock lock = new ReentrantReadWriteLock();//讀寫鎖  
  39.     private Map<String, Object> cache = new HashMap<String, Object>();//緩衝  
  40.       
  41.     private CachedData(){  
  42.     }  
  43.       
  44.     public static CachedData getInstance(){  
  45.         return cachedData;  
  46.     }  
  47.       
  48.     // 讀取緩衝:  
  49.     public Object read(String key) {  
  50.         lock.readLock().lock();  
  51.         Object obj = null;  
  52.         try {  
  53.             obj = cache.get(key);  
  54.             if (obj == null) {  
  55.                 lock.readLock().unlock();  
  56.                 // 在這裡的時候,其他的線程有可能擷取到鎖  
  57.                 lock.writeLock().lock();  
  58.                 try {  
  59.                     if (obj == null) {  
  60.                         obj = "尋找資料庫"; // 實際動作是尋找資料庫  
  61.                         // 把資料更新到緩衝中:  
  62.                         cache.put(key, obj);  
  63.                     }  
  64.                 } finally {  
  65.                     // 當前線程在擷取到寫鎖的過程中,可以擷取到讀鎖,這叫鎖的重入,然後導致了寫鎖的降級,稱為降級鎖。  
  66.                     // 利用重入可以將寫鎖降級,但只能在當前線程保持的所有寫入鎖都已經釋放後,才允許重入 reader使用  
  67.                     // 它們。所以在重入的過程中,其他的線程不會有擷取到鎖的機會(這樣做的好處)。試想,先釋放寫鎖,在  
  68.                     // 上讀鎖,這樣做有什麼弊端?--如果這樣做,那麼在釋放寫鎖後,在得到讀鎖前,有可能被其他線程打斷。  
  69.                     // 重入————>降級鎖的步驟:先擷取寫入鎖,然後擷取讀取鎖,最後釋放寫入鎖(重點)  
  70.                     lock.readLock().lock();   
  71.                     lock.writeLock().unlock();  
  72.                 }  
  73.             }  
  74.         } finally {  
  75.             lock.readLock().unlock();  
  76.         }  
  77.         return obj;  
  78.     }  
  79. }  


例子2:

[java] view plaincopy 
    1. import java.util.Map;  
    2. import java.util.TreeMap;  
    3. import java.util.concurrent.locks.Lock;  
    4. import java.util.concurrent.locks.ReadWriteLock;  
    5. import java.util.concurrent.locks.ReentrantReadWriteLock;  
    6.   
    7. import javax.xml.crypto.Data;  
    8.   
    9. /** 
    10.  * @author amber2012 
    11.  *  
    12.  * jdk文檔中關於ReentrantReadWriteLock類使用的一個很好的例子,以下是具體的介紹: 
    13.  *  
    14.  * 在使用某些種類的 Collection 時,可以使用 ReentrantReadWriteLock 來提高並發性。通常,在預期 collection 
    15.  * 很大,讀取者線程訪問它的次數多於寫入者線程,並且 entail 操作的開銷高於同步開銷時,這很值得一試。例如,以下 
    16.  * 是一個使用 TreeMap 的類,預期它很大,並且能被同時訪問。  
    17.  */  
    18. public class RWDictionary {  
    19.   
    20.     private final Map<String, Data> map = new TreeMap<String, Data>();  
    21.     private final ReadWriteLock rwl = new ReentrantReadWriteLock();  
    22.     private final Lock readLock = rwl.readLock();  
    23.     private final Lock writeLock = rwl.writeLock();  
    24.   
    25.     public Data get(String key) {  
    26.         readLock.lock();  
    27.         try {  
    28.             return map.get(key);  
    29.         } finally {  
    30.             readLock.unlock();  
    31.         }  
    32.     }  
    33.   
    34.     public String[] allKeys() {  
    35.         readLock.lock();  
    36.         try {  
    37.             return (String[]) map.keySet().toArray();  
    38.         } finally {  
    39.             readLock.unlock();  
    40.         }  
    41.     }  
    42.   
    43.     public Data put(String key, Data value) {  
    44.         writeLock.lock();  
    45.         try {  
    46.             return map.put(key, value);  
    47.         } finally {  
    48.             writeLock.unlock();  
    49.         }  
    50.     }  
    51.   
    52.     public void clear() {  
    53.         writeLock.lock();  
    54.         try {  
    55.             map.clear();  
    56.         } finally {  
    57.             writeLock.unlock();  
    58.         }  
    59.     }  
    60. }  

轉寄 :java線程:互斥鎖與讀寫鎖

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.