第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

并發(fā)鎖之 Lock 接口

1. 前言

本節(jié)內(nèi)容主要是對(duì) Java 并發(fā)鎖之 Lock 接口進(jìn)行介紹,Lock 是類(lèi)似于 synchronized 的另外一種鎖的使用,那么本節(jié)我們會(huì)對(duì) Lock 進(jìn)行詳細(xì)的介紹,主要知識(shí)點(diǎn)如下:

  • Lock 接口的介紹,這是我們開(kāi)始認(rèn)識(shí) Lock 的敲門(mén)磚,本節(jié)課程的基礎(chǔ)知識(shí);
  • Lock 接口相比于 synchronized 關(guān)鍵字的優(yōu)點(diǎn),這也是我們學(xué)習(xí) Lock 接口的意義所在;
  • Lock 接口的常用方法介紹,了解 Lock 接口中的常用方法,是本節(jié)內(nèi)容的核心知識(shí)點(diǎn)。

Lock 是一個(gè)接口,并非一個(gè)實(shí)現(xiàn)類(lèi),本節(jié)內(nèi)容主要對(duì) Lock 接口進(jìn)行一個(gè)意義、結(jié)構(gòu)及方法的介紹,為后續(xù)講解 Lock 接口的實(shí)現(xiàn)類(lèi)常用鎖奠定一個(gè)扎實(shí)的基礎(chǔ)。

2. Lock 接口的介紹

Lock 接口的誕生:在 Java 中鎖的實(shí)現(xiàn)可以由 synchronized 關(guān)鍵字來(lái)完成,但在 Java5 之后,出現(xiàn)了一種新的方式來(lái)實(shí)現(xiàn),即 Lock 接口。

誕生的意義:Lock 接口支持那些語(yǔ)義不同(重入、公平等)的鎖規(guī)則,可以在非阻塞式結(jié)構(gòu)的上下文(包括 hand-over-hand 和鎖重排算法)中使用這些規(guī)則。主要的實(shí)現(xiàn)是 ReentrantLock。對(duì)于 ReentrantLock,后續(xù)有專(zhuān)門(mén)的小節(jié)進(jìn)行講解。

JDK 1.5 前的 synchronized:在多線程的情況下,當(dāng)一段代碼被 synchronized 修飾之后,同一時(shí)刻只能被一個(gè)線程訪問(wèn),其他線程都必須等到該線程釋放鎖之后才能有機(jī)會(huì)獲取鎖訪問(wèn)這段代碼。

Lock 接口: 實(shí)現(xiàn)提供了比使用 synchronized 方法和語(yǔ)句可獲得的更廣泛的鎖定操作。此實(shí)現(xiàn)允許更靈活的結(jié)構(gòu),可以具有差別很大的屬性,可以支持多個(gè)相關(guān)的 Condition 對(duì)象。

Lock 相對(duì)于 synchronized 關(guān)鍵字而言更加靈活,你可以自由得選擇你想要加鎖的地方。當(dāng)然更高的自由度也帶來(lái)更多的責(zé)任。

使用示例:我們通常會(huì)在 try catch 模塊中使用 Lock 關(guān)鍵字,在 finally 模塊中釋放鎖。

	 Lock lock = new ReentrantLock(); //通過(guò)子類(lèi)進(jìn)行創(chuàng)建,此處以ReentrantLock進(jìn)行舉例
     lock.lock(); //加鎖
     try {
         // 對(duì)上鎖的邏輯進(jìn)行操作
     } finally {
         lock.unlock(); //釋放鎖
     }

3. Lock 接口與 synchronized 關(guān)鍵字的區(qū)別

  • 實(shí)現(xiàn):synchronized 關(guān)鍵字基于 JVM 層面實(shí)現(xiàn),JVM 控制鎖的獲取和釋放。Lock 接口基于 JDK 層面,手動(dòng)進(jìn)行鎖的獲取和釋放;
  • 使用:synchronized 關(guān)鍵字不用手動(dòng)釋放鎖,Lock 接口需要手動(dòng)釋放鎖,在 finally 模塊中調(diào)用 unlock 方法;
  • 鎖獲取超時(shí)機(jī)制:synchronized 關(guān)鍵字不支持,Lock 接口支持;
  • 獲取鎖中斷機(jī)制:synchronized 關(guān)鍵字不支持,Lock 接口支持;
  • 釋放鎖的條件:synchronized 關(guān)鍵字在滿足占有鎖的線程執(zhí)行完畢,或占有鎖的線程異常退出,或占有鎖的線程進(jìn)入 waiting 狀態(tài)才會(huì)釋放鎖。Lock 接口調(diào)用 unlock 方法釋放鎖;
  • 公平性:synchronized 關(guān)鍵字為非公平鎖。Lock 接口可以通過(guò)入?yún)⒆孕性O(shè)置鎖的公平性。

4. Lock 接口相比 synchronized 關(guān)鍵字的優(yōu)勢(shì)

我們通過(guò)兩個(gè)個(gè)案例分析來(lái)了解 Lock 接口的優(yōu)勢(shì)所在。
案例 1 :在使用 synchronized 關(guān)鍵字的情形下,假如占有鎖的線程由于要等待 IO 或者其他原因(比如調(diào)用 sleep 方法)被阻塞了,但是又沒(méi)有釋放鎖,那么其他線程就只能一直等待,別無(wú)他法。這會(huì)極大影響程序執(zhí)行效率。

案例 1 分析:該案例體現(xiàn)了 synchronized 的缺陷,當(dāng)線程被占有時(shí),其他線程會(huì)陷入無(wú)條件的長(zhǎng)期等待。這是非常可怕的,因?yàn)橄到y(tǒng)資源有限,最終可能導(dǎo)致系統(tǒng)崩潰。

案例 1 解決:Lock 接口中的 tryLock (long time, TimeUnit unit) 方法或者響應(yīng)中斷 lockInterruptibly () 方法,能夠解決這種長(zhǎng)期等待的情況。

案例 2 :我們知道,當(dāng)多個(gè)線程讀寫(xiě)文件時(shí),讀操作和寫(xiě)操作會(huì)發(fā)生沖突現(xiàn)象,寫(xiě)操作和寫(xiě)操作也會(huì)發(fā)生沖突現(xiàn)象,但是讀操作和讀操作不會(huì)發(fā)生沖突現(xiàn)象。
但是如果采用 synchronized 關(guān)鍵字實(shí)現(xiàn)同步的話,就會(huì)導(dǎo)致一個(gè)問(wèn)題,即當(dāng)多個(gè)線程都只是進(jìn)行讀操作時(shí),也只有一個(gè)線程可以進(jìn)行讀操作,其他線程只能等待鎖的釋放而無(wú)法進(jìn)行讀操作。

案例 2 分析:該案例體現(xiàn)了 synchronized 的缺陷,悲觀鎖的缺陷。我們說(shuō)過(guò),如果只是讀操作,沒(méi)有增刪改操作的話,多線程環(huán)境下無(wú)需加鎖。但是這種情況下,如果在同一時(shí)間多個(gè)線程進(jìn)行讀操作,synchronized 會(huì) block 其他的讀操作,這是不合理的。

案例 2 解決:Lock 接口家族也可以解決這種情況,后續(xù)我們會(huì)對(duì) ReadWriteLock 接口的一個(gè)子類(lèi) ReentrantReadWriteLock 進(jìn)行講解。

總結(jié):Lock 接口實(shí)現(xiàn)提供了比使用 synchronized 方法和語(yǔ)句可獲得的更廣泛的鎖定操作,能夠解決 synchronized 不能夠避免的問(wèn)題。

5. Lock 接口的常用方法

我們來(lái)簡(jiǎn)單的看下,JDK 中 Lock 接口的源碼中所包含的方法:

public interface Lock {
    void lock();
    void lockInterruptibly() throws InterruptedException;
    boolean tryLock();
    boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
    void unlock();
    Condition newCondition();
}

方法介紹

  1. void lock():獲取鎖。如果鎖不可用,出于線程調(diào)度目的,將禁用當(dāng)前線程,并且在獲得鎖之前,該線程將一直處于休眠狀態(tài);
  2. void lockInterruptibly():如果當(dāng)前線程未被中斷,則獲取鎖;
  3. boolean tryLock():僅在調(diào)用時(shí)鎖為空閑狀態(tài)才獲取該鎖。如果鎖可用,則獲取鎖,并立即返回值 true。如果鎖不可用,則此方法將立即返回值 false;
  4. boolean tryLock(long time, TimeUnit unit):如果鎖在給定的等待時(shí)間內(nèi)空閑,并且當(dāng)前線程未被中斷,則獲取鎖;
  5. void unlock():釋放鎖。在等待條件前,鎖必須由當(dāng)前線程保持。調(diào)用 Condition.await () 將在等待前以原子方式釋放鎖,并在等待返回前重新獲取鎖;
  6. Condition newCondition():返回綁定到此 Lock 實(shí)例的新 Condition 實(shí)例。

Tips:對(duì) Lock 接口方法的使用,我們必須基于子類(lèi)進(jìn)行 Lock 的創(chuàng)建來(lái)展示,由于目前我們還未接觸 Lock 接口的實(shí)現(xiàn)子類(lèi),此處只做方法的介紹。后續(xù)對(duì) ReentrantLock 進(jìn)行講解時(shí),會(huì)進(jìn)行深入講解。

6. 小結(jié)

本節(jié)主要是對(duì) Lock 接口的常用方法進(jìn)行了介紹,為本節(jié)內(nèi)容的核心知識(shí)。除了方法的介紹外,本節(jié)內(nèi)容不容忽視的一個(gè)重點(diǎn)內(nèi)容是 synchronized 關(guān)鍵字與 Lock 接口的區(qū)別,以及 Lock 接口的優(yōu)勢(shì)所在。

掌握本節(jié)內(nèi)容,有助于同學(xué)對(duì)后續(xù)實(shí)現(xiàn)類(lèi)鎖的學(xué)習(xí),為后續(xù)的學(xué)習(xí)奠定了良好的基礎(chǔ)。