程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 舉例說明Java多線程編程中讀寫鎖的使用

舉例說明Java多線程編程中讀寫鎖的使用

編輯:關於C語言

以下示例為 Java api並發庫中 ReentrantReadWriteLock自帶的實例,下面進行解讀

? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class CachedData { Object data; volatile boolean cacheValid; ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); void processCachedData() { rwl.readLock().lock();//@1 if (!cacheValid) { // Must release read lock before acquiring write lock rwl.readLock().unlock();//@4 rwl.writeLock().lock();//@2 // Recheck state because another thread might have acquired // write lock and changed state before we did. if (!cacheValid) {//@3 data = ... cacheValid = true; } // Downgrade by acquiring read lock before releasing write lock rwl.readLock().lock(); rwl.writeLock().unlock(); // Unlock write, still hold read } use(data); rwl.readLock().unlock(); } }

當有n多線程 使用同一CachedData 實例對象 調用processCachedData方法時,就會產生線程的並發問題.
@1行,當有線程正在對數據進行 寫操作的時候,運行到@1行的線程要等待 寫操作的完成,因為第一個運行到@2的線程會加上鎖,然後對數據進行需該,期間不允許任何線程進行讀或者是寫的操作,

當寫完後,在該線程上加上讀鎖操作,以防止解寫鎖後,別的線程對數據再次進行寫時出錯.在第一個運行到@2的線程之後的很多線程,

可能已經運行到了@4,當對數據修改好之後,解除掉寫鎖,別的線程就會執行到@2,這時第一個線程已經經數據修改好了,所以有了@3的判斷。

在編寫多線程程序的時候,要置於並發線程的環境下考慮,巧妙的運用ReentrantReadWriteLock,在運用時,注意鎖的降級,寫入鎖可以獲得讀鎖,讀鎖不可以獲得寫入鎖,所以在上寫入鎖時,必須先將讀鎖進行解除,然後上讀鎖。

使用時注意的幾個方面:
   讀鎖是排寫鎖操作的,讀鎖不排讀鎖操作,多個讀鎖可以並發不阻塞。即在讀鎖獲取後和讀鎖釋放之前,寫鎖並不能被任何線程獲得,
      多個讀鎖同時作用期間,試圖獲取寫鎖的線程都處於等待狀態,當最後一個讀鎖釋放後,試圖獲取寫鎖的線程才有機會獲取寫鎖。
   寫鎖是排寫鎖、排讀鎖操作的。當一個線程獲取到寫鎖之後,其他試圖獲取寫鎖和試圖獲取讀鎖的線程都處於等待狀態,直到寫鎖被釋放。
寫鎖是可以獲得讀鎖的,即:

? 1 2 3 4 rwl.writeLock().lock(); //在寫鎖狀態中,可以獲取讀鎖 rwl.readLock().lock(); rwl.writeLock().unlock();

  讀鎖是不能夠獲得寫鎖的,如果要加寫鎖,本線程必須釋放所持有的讀鎖,即:

? 1 2 3 4 5 rwl.readLock().lock(); //...... //必須釋放掉讀鎖,才能夠加寫鎖 rwl.readLock().unlock(); rwl.writeLock().lock();

讀寫鎖是線程讀寫同一文件所需要用到的,讀寫鎖是什麼東西在這裡不做過多的解釋,可以自己去百度或谷歌去搜一下。

謹在此附上我自己寫的緩存系統的簡單實現,你從中也能悟出緩存實現的基本思想

緩存裡面有數據就從緩存中取,沒有就給你從其他地方得到。

? 1 2 3 4 5 6 7 8 9 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 35 36 37 38 39 40 41 42 43 package cn.com.scl.cache import Java.util.HashMap; import Java.util.Map; import Java.util.concurrent.locks.ReadWriteLock; import Java.util.concurrent.locks.ReentrantReadWriteLock; /** * 緩存的實現,每個線程只能獲得他自己的緩存,也應該是單例的 * 本類沒有去實現單例,如果需要的話可以自行去實現 * @author scl * */ public class CacheSystem { private Map<String, Object> cache = new HashMap<String,Object>(); private ReadWriteLock rwl = new ReentrantReadWriteLock(); public Object getData(String key){ //先從緩存中去取數據,先加上讀鎖 rwl.readLock().lock(); Object obj = null; try{ obj = cache.get(key); if(obj == null){ //先解除讀鎖,在上寫鎖(必須先解除讀鎖才能成功上寫鎖) rwl.readLock().unlock(); rwl.writeLock().lock(); //去數據庫取數據,再判斷一次是否為null,因為有可能多個線程獲得寫鎖 try{ if(obj == null){ obj = new String("obj is get from db"); } }finally{ //先上讀鎖,然後再解除寫鎖(這樣可以成功完成,在解除寫鎖前獲得讀鎖,寫鎖被降級--這翻譯的api上的) rwl.readLock().lock(); rwl.writeLock().unlock();//解除寫鎖,讀鎖仍然持有 } } }finally{ rwl.readLock().unlock(); } return obj; } }
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved