成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

JAVA并發(fā)編程之-ReentrantLock鎖原理解讀

荊兆峰 / 1611人閱讀

摘要:作者畢來生微信鎖狀態(tài)轉(zhuǎn)換分類以后幫助我們提供了線程同步機(jī)制,通過顯示定義同步鎖來實(shí)現(xiàn)對(duì)象之間的同步。等待重新嘗試因?yàn)樵谥惺怯藐P(guān)鍵字聲明的,故可以在線程間可見再次判斷一下能否持有鎖可能線程同步代碼執(zhí)行得比較快,已經(jīng)釋放了鎖,不可以就返回。

作者 : 畢來生
微信: 878799579
鎖狀態(tài)轉(zhuǎn)換

Lock分類

? Jdk1.5以后幫助我們提供了線程同步機(jī)制,通過顯示定義同步鎖來實(shí)現(xiàn)對(duì)象之間的同步。還是Doug Lea這個(gè)家伙寫的。相信讀過源碼的人在很多地方都可以看到這個(gè)家伙。

? Lock可以顯示的進(jìn)行加鎖,解鎖。但是每次只能有一個(gè)線程對(duì)Lock對(duì)象加鎖

? Lock實(shí)現(xiàn)結(jié)構(gòu)如下圖所示:

? 按照使用的常用度,分別標(biāo)注了(1),(2),(3)。接下來我們就主要學(xué)習(xí)一下ReentrantLock的使用

可重入鎖

? ReentrantLock實(shí)現(xiàn)的前提就是AbstractQueuedSynchronizer,簡(jiǎn)稱AQS.。核心方法內(nèi)部實(shí)現(xiàn)均在AQS中,后續(xù)我們?cè)谠敿?xì)解讀AQS相關(guān)知識(shí)點(diǎn)以及使用場(chǎng)景。我們先來看一段偽代碼用以表述可重入鎖的使用情況。接下來我們來詳細(xì)分析獲取鎖以及釋放鎖內(nèi)部實(shí)現(xiàn)到底做了什么事情。

package org.bilaisheng.juc;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @Author: bilaisheng
 * @Wechat: 878799579
 * @Date: 2019/1/3 22:55
 * @Todo: 偽代碼僅演示使用
 * @Version : JDK11 , IDEA2018
 */
public class ReentrantLockTest {


    public static void main(String[] args) {
        Lock lock = new ReentrantLock();

        // 獲取鎖
        lock.lock();
        
        // access the resource protected by this lock
        // do something
        
        // 釋放鎖
        lock.unlock();

    }
}
Sync對(duì)象剖析
     /** Synchronizer providing all implementation mechanics */
    private final Sync sync;

    /**
     * Base of synchronization control for this lock. Subclassed
     * into fair and nonfair versions below. Uses AQS state to
     * represent the number of holds on the lock.
     */
    abstract static class Sync extends AbstractQueuedSynchronizer {
        // xxxx
    }    

他會(huì)根據(jù)傳入構(gòu)造方法的布爾類型參數(shù)實(shí)例化出Sync的實(shí)現(xiàn)類FairSync和NoFairSync。

FairSync: 公平的Sync

NoFairSync : 不公平的Sync

public ReentrantLock(boolean fair) {
    sync = fair ? new FairSync() : new NonfairSync();
}
ReentrantLock.lock()實(shí)現(xiàn)原理

? 我們用的比較多的ReentrantLock是非公平鎖,我們來用一張圖來分析一下看看它是如何實(shí)現(xiàn)的。

上圖就做了兩件事情:

1、設(shè)置AbstractQueuedSynchronizer的state為1

2、設(shè)置AbstractOwnableSynchronizer的thread為當(dāng)前線程

線程A正在執(zhí)行中,status = 1。

線程B嘗試?yán)肅AS去判斷state是不是0,是0就設(shè)置為1,當(dāng)然這一步操作肯定是失敗的,因?yàn)榫€程A已經(jīng)將state設(shè)置成了1,所以此時(shí)肯定是失敗的。

失敗了之后進(jìn)入FIFO等待隊(duì)列。等待重新嘗試

/**
 * Performs non-fair tryLock.  tryAcquire is implemented in
 * subclasses, but both need nonfair try for trylock method.
 */
@ReservedStackAccess
final boolean nonfairTryAcquire(int acquires) {
    final Thread current = Thread.currentThread();
    int c = getState();
    if (c == 0) {
        if (compareAndSetState(0, acquires)) {
            setExclusiveOwnerThread(current);
            return true;
        }
    }
    else if (current == getExclusiveOwnerThread()) {
        int nextc = c + acquires;
        if (nextc < 0) // overflow
            throw new Error("Maximum lock count exceeded");
        setState(nextc);
        return true;
    }
    return false;
}

因?yàn)樵贏bstractQueuedSynchronizer中state是用volatile關(guān)鍵字聲明的,故可以在線程間可見

/**
 * The synchronization state.
 */
private volatile int state;

再次判斷一下能否持有鎖(可能線程A同步代碼執(zhí)行得比較快,已經(jīng)釋放了鎖),不可以就返回false。

根據(jù)上方代碼可以看出同一個(gè)鎖最多能重入Integer.MAX_VALUE次,也就是2147483647。

ReentrantLock.unLock()實(shí)現(xiàn)原理

此處較為簡(jiǎn)單。附上調(diào)用關(guān)系鏈路

// 步驟一
public void unlock() {
    sync.release(1);
}

// 步驟二 : AbstractQueuedSynchronizer
public final boolean release(int arg) {
    if (tryRelease(arg)) {
        Node h = head;
        if (h != null && h.waitStatus != 0)
           unparkSuccessor(h);
        return true;
    }
    return false;
}

//步驟二 : ReentrantLock
 @ReservedStackAccess
protected final boolean tryRelease(int releases) {
    int c = getState() - releases;
    if (Thread.currentThread() != getExclusiveOwnerThread())
        throw new IllegalMonitorStateException();
    boolean free = false;
    if (c == 0) {
        free = true;
        setExclusiveOwnerThread(null);
    }
    setState(c);
    return free;
}

當(dāng)一條線程對(duì)同一個(gè)ReentrantLock全部解鎖之后,AQS的state就是0了,AbstractOwnableSynchronizer的exclusiveOwnerThread將被設(shè)置為null,這樣就表示沒有線程占有鎖,方法返回true。

喜歡就關(guān)注我吧

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/75675.html

相關(guān)文章

  • 手撕面試官系列(七):面試必備常問并發(fā)編程高級(jí)面試專題

    摘要:如何在線程池中提交線程內(nèi)存模型相關(guān)問題什么是的內(nèi)存模型,中各個(gè)線程是怎么彼此看到對(duì)方的變量的請(qǐng)談?wù)動(dòng)惺裁刺攸c(diǎn),為什么它能保證變量對(duì)所有線程的可見性既然能夠保證線程間的變量可見性,是不是就意味著基于變量的運(yùn)算就是并發(fā)安全的請(qǐng)對(duì)比下對(duì)比的異同。 并發(fā)編程高級(jí)面試面試題 showImg(https://upload-images.jianshu.io/upload_images/133416...

    Charles 評(píng)論0 收藏0
  • 后臺(tái)開發(fā)常問面試題集錦(問題搬運(yùn)工,附鏈接)

    摘要:基礎(chǔ)問題的的性能及原理之區(qū)別詳解備忘筆記深入理解流水線抽象關(guān)鍵字修飾符知識(shí)點(diǎn)總結(jié)必看篇中的關(guān)鍵字解析回調(diào)機(jī)制解讀抽象類與三大特征時(shí)間和時(shí)間戳的相互轉(zhuǎn)換為什么要使用內(nèi)部類對(duì)象鎖和類鎖的區(qū)別,,優(yōu)缺點(diǎn)及比較提高篇八詳解內(nèi)部類單例模式和 Java基礎(chǔ)問題 String的+的性能及原理 java之yield(),sleep(),wait()區(qū)別詳解-備忘筆記 深入理解Java Stream流水...

    spacewander 評(píng)論0 收藏0
  • 后臺(tái)開發(fā)常問面試題集錦(問題搬運(yùn)工,附鏈接)

    摘要:基礎(chǔ)問題的的性能及原理之區(qū)別詳解備忘筆記深入理解流水線抽象關(guān)鍵字修飾符知識(shí)點(diǎn)總結(jié)必看篇中的關(guān)鍵字解析回調(diào)機(jī)制解讀抽象類與三大特征時(shí)間和時(shí)間戳的相互轉(zhuǎn)換為什么要使用內(nèi)部類對(duì)象鎖和類鎖的區(qū)別,,優(yōu)缺點(diǎn)及比較提高篇八詳解內(nèi)部類單例模式和 Java基礎(chǔ)問題 String的+的性能及原理 java之yield(),sleep(),wait()區(qū)別詳解-備忘筆記 深入理解Java Stream流水...

    xfee 評(píng)論0 收藏0
  • 后臺(tái)開發(fā)常問面試題集錦(問題搬運(yùn)工,附鏈接)

    摘要:基礎(chǔ)問題的的性能及原理之區(qū)別詳解備忘筆記深入理解流水線抽象關(guān)鍵字修飾符知識(shí)點(diǎn)總結(jié)必看篇中的關(guān)鍵字解析回調(diào)機(jī)制解讀抽象類與三大特征時(shí)間和時(shí)間戳的相互轉(zhuǎn)換為什么要使用內(nèi)部類對(duì)象鎖和類鎖的區(qū)別,,優(yōu)缺點(diǎn)及比較提高篇八詳解內(nèi)部類單例模式和 Java基礎(chǔ)問題 String的+的性能及原理 java之yield(),sleep(),wait()區(qū)別詳解-備忘筆記 深入理解Java Stream流水...

    makeFoxPlay 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<