Java多線程進階(三)—— J.U.C之locks框架:ReentrantLock

timg (2).jpeg

本文首發於一世流雲的專欄: https://segmentfault.com/blog...

1、ReentrantLock類簡介

ReentrantLock類,實現了Lock接口,是一種可重入獨佔鎖,它具備與使用 synchronized 相同的一些基本行爲和語義,但功能更強大。ReentrantLock內部經過內部類實現了AQS框架(AbstractQueuedSynchronizer)的API來實現獨佔鎖的功能。segmentfault

1.1 類聲明

ReentrantLock類直接實現了Lock接口:
ReentrantLock類聲明api

1.2 構造聲明

ReentrantLock類提供了兩類構造器:
ReentrantLock構造聲明多線程

ReentrantLock類的其中一個構造器提供了指定公平策略 / 非公平策略的功能,默認爲非公平策略框架

公平策略:在多個線程爭用鎖的狀況下,公平策略傾向於將訪問權授予等待時間最長的線程。也就是說,至關於有一個線程等待隊列,先進入等待隊列的線程後續會先得到鎖,這樣按照「先來後到」的原則,對於每個等待線程都是公平的。
非公平策略:在多個線程爭用鎖的狀況下,可以最終得到鎖的線程是隨機的(由底層OS調度)。

注意:通常狀況下,使用公平策略的程序在多線程訪問時,整體吞吐量(即速度很慢,經常極其慢)比較低,由於此時在線程調度上面的開銷比較大。spa

舉個例子:
假設採用公平策略,線程A首先獲取了鎖,線程B和線程C等待獲取鎖,以下圖:
image.png線程

當線程A釋放鎖時,線程B將經歷從 掛起->喚醒 的線程調度過程,線程調度很是耗時。code

在線程B的 掛起->喚醒 階段:blog

  1. 若是採用非公平策略,那麼線程C能夠當即獲取鎖,線程C使用完並釋放鎖後,線程B可能纔剛喚醒完成;此時線程B又能夠去獲取鎖,這樣線程B和線程C的效率都獲得提高,系統吞吐量提高;
  2. 若是採用公平策略,線程C即便可用,也要等到線程調度完成,整個系統的吞吐量下降。

所以,當線程持有鎖的時間相對較長或者線程請求鎖的平均時間間隔較長時,能夠考慮使用公平策略。此時線程調度產生的耗時間隔影響會較小。接口

1.3 使用方式

ReentrantLock的典型調用方式以下:隊列

class X {
    private final ReentrantLock lock = new ReentrantLock();
    // ...
    public void m() {
        lock.lock(); // block until condition holds
        try {
            // ... method body
        } finally {
            lock.unlock();
        }
    }
}

2、ReentrantLock類原理

ReentrantLock的源碼很是簡單,它經過內部類實現了AQS框架,Lock接口的實現僅僅是對AQS的api的簡單封裝,
參見AQS原理:Java多線程進階(七)—— juc-locks鎖框架:AQS獨佔功能剖析(2)

相關文章
相關標籤/搜索