本文首發於一世流雲的專欄: https://segmentfault.com/blog...
ReentrantLock類,實現了Lock接口,是一種可重入的獨佔鎖,它具備與使用 synchronized
相同的一些基本行爲和語義,但功能更強大。ReentrantLock內部經過內部類實現了AQS框架(AbstractQueuedSynchronizer)的API來實現獨佔鎖的功能。segmentfault
ReentrantLock類直接實現了Lock接口:
api
ReentrantLock類提供了兩類構造器:
多線程
ReentrantLock類的其中一個構造器提供了指定公平策略 / 非公平策略的功能,默認爲非公平策略。框架
公平策略:在多個線程爭用鎖的狀況下,公平策略傾向於將訪問權授予等待時間最長的線程。也就是說,至關於有一個線程等待隊列,先進入等待隊列的線程後續會先得到鎖,這樣按照「先來後到」的原則,對於每個等待線程都是公平的。
非公平策略:在多個線程爭用鎖的狀況下,可以最終得到鎖的線程是隨機的(由底層OS調度)。
注意:通常狀況下,使用公平策略的程序在多線程訪問時,整體吞吐量(即速度很慢,經常極其慢)比較低,由於此時在線程調度上面的開銷比較大。spa
舉個例子:
假設採用公平策略,線程A首先獲取了鎖,線程B和線程C等待獲取鎖,以下圖:
線程
當線程A釋放鎖時,線程B將經歷從 掛起->喚醒 的線程調度過程,線程調度很是耗時。code
在線程B的 掛起->喚醒 階段:blog
所以,當線程持有鎖的時間相對較長或者線程請求鎖的平均時間間隔較長時,能夠考慮使用公平策略。此時線程調度產生的耗時間隔影響會較小。接口
ReentrantLock的典型調用方式以下:隊列
class X { private final ReentrantLock lock = new ReentrantLock(); // ... public void m() { lock.lock(); // block until condition holds try { // ... method body } finally { lock.unlock(); } } }
ReentrantLock的源碼很是簡單,它經過內部類實現了AQS框架,Lock接口的實現僅僅是對AQS的api的簡單封裝,
參見AQS原理:Java多線程進階(七)—— juc-locks鎖框架:AQS獨佔功能剖析(2)