java中讀寫鎖的使用(ReadWriteLock)

一、在JDK文檔中關於讀寫鎖的相關說明

ReadWriteLock 維護了一對相關的 鎖 ,一個用於只讀操作,另一個用於寫入操作。只要沒有 writer, 讀取鎖 可以由多個 reader 線程同時保持。 寫入鎖 是獨佔的。
所有 ReadWriteLock 實現都必須保證 writeLock 操作的內存同步效果也要保持與相關 readLock 的聯繫。也就是說,成功獲取讀鎖的線程會看到寫入鎖之前版本所做的所有更新。
與互斥鎖相比,讀-寫鎖允許對共享數據進行更高級別的併發訪問。雖然一次只有一個線程( writer 線程)可以修改共享數據,但在許多情況下,任何數量的線程可以同時讀取共享數據( reader 線程),讀-寫鎖利用了這一點。從理論上講,與互斥鎖相比,使用讀-寫鎖所允許的併發性增強將帶來更大的性能提高。在實踐中,只有在多處理器上並且只在訪問模式適用於共享數據時,才能完全實現併發性增強。
與互斥鎖相比,使用讀-寫鎖能否提升性能則取決於讀寫操作期間讀取數據相對於修改數據的頻率,以及數據的爭用——即在同一時間試圖對該數據執行讀取或寫入操作的線程數。例如,某個最初用數據填充並且之後不經常對其進行修改的 collection,因爲經常對其進行搜索(比如搜索某種目錄),所以這樣的 collection 是使用讀-寫鎖的理想候選者。但是,如果數據更新變得頻繁,數據在大部分時間都被獨佔鎖,這時,就算存在併發性增強,也是微不足道的。更進一步地說,如果讀取操作所用時間太短,則讀-寫鎖實現(它本身就比互斥鎖複雜)的開銷將成爲主要的執行成本,在許多讀-寫鎖實現仍然通過一小段代碼將所有線程序列化時更是如此。最終,只有通過分析和測量,才能確定應用程序是否適合使用讀-寫鎖。
儘管讀-寫鎖的基本操作是直截了當的,但實現仍然必須作出許多決策,這些決策可能會影響給定應用程序中讀-寫鎖的效果。這些策略的例子包括:
1、在 writer 釋放寫入鎖時,reader 和 writer 都處於等待狀態,在這時要確定是授予讀取鎖還是授予寫入鎖。Writer 優先比較普遍,因爲預期寫入所需的時間較短並且不那麼頻繁。Reader 優先不太普遍,因爲如果 reader 正如預期的那樣頻繁和持久,那麼它將導致對於寫入操作來說較長的時延。公平或者“按次序”實現也是有可能的。
2、在 reader 處於活動狀態而 writer 處於等待狀態時,確定是否向請求讀取鎖的 reader 授予讀取鎖。Reader 優先會無限期地延遲 writer,而 writer 優先會減少可能的併發。
3、確定是否重新進入鎖:可以使用帶有寫入鎖的線程重新獲取它嗎?可以在保持寫入鎖的同時獲取讀取鎖嗎?可以重新進入寫入鎖本身嗎?
4、可以將寫入鎖在不允許其他 writer 干涉的情況下降級爲讀取鎖嗎?可以優先於其他等待的 reader 或 writer 將讀取鎖升級爲寫入鎖嗎?
當評估給定實現是否適合您的應用程序時,應該考慮所有這些情況。

二、讀寫鎖的機制

1、”讀-讀”不互斥,比如當前有10個線程去讀(沒有線程去寫),這個10個線程可以併發讀,而不會堵塞。
2、 “讀-寫”互斥,當前有寫的線程的時候,那麼讀取線程就會堵塞,反過來,有讀的線程在使用的時候,寫的線程也會堵塞,就看誰先拿到鎖了。
3、 “寫-寫”互斥,寫線程都是互斥的,如果有兩個線程去寫,A線程先拿到鎖就先寫,B線程就堵塞直到A線程釋放鎖。

三、讀寫鎖的適用場景

1、讀多寫少的高併發環境下,可以說這個場景算是最適合使用ReadWriteLock 了。

四、使用方式

我就以在統一監控平臺中的數據接收中心的緩存操作做爲使用例子了。
1、業務需求: 10分鐘從數據庫中讀取所有的TP監控點到緩存中,數據接收中心實時接收到的TP數據需要判斷數據中的TP監控KEY是否有效,如果無效就將此TP數據中的監控點放置到自動跑KEY中去。
2、程序要求 :在更新緩存時,判斷KEY是否有效需要堵塞,直到緩存更新完成,程序啓動時首先需要加載數據至緩存,然後每10分鐘更新一次緩存。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章