鎖的分類以及相關講解與synchronized區別

2021-10-04 22:34:49 字數 4913 閱讀 4242

1.鎖的分類#

2.深入理解lock介面#

lock的使用

lock與synchronized的區別

lock 獲取鎖與釋放鎖的過程,都需要程式設計師手動的控制 lock用的是樂觀鎖方式。

所謂樂觀鎖就是,每次不加鎖而是假設沒有衝突而去完成某項操作,如果因為衝突失敗就重試,直到成功為止。樂觀鎖實現的機制就 是cas操作

​ synchronized託管給jvm執行 原始採用的是cpu悲觀鎖機制,即執行緒獲得的是獨佔鎖。獨佔鎖意味著其他執行緒只能依靠阻塞來等待執行緒釋放鎖。

實現了lock介面的鎖 各個方法的簡介

copy

/** * 使用lock */ public class lockdemo public static void main(string args) catch (interruptedexception e) } //在每個執行緒只想完後呼叫cutdown countdownlatch.countdown(); }).start(); } while (true) } system.out.println(num); } }

3.實現屬於自己的鎖#

實現lock介面

使用wait notify

4.abstractqueuedsynchronizer**#

​ abstractqueuedsynchronizer -- 為實現依賴於先進先出 (fifo) 等待佇列的阻塞鎖和相關同步器(訊號量、事件,等等)提供乙個框架。

copy

此類的設計目標是成為依靠單個原子 int 值來表示狀態的大多數同步器的乙個有用基礎。 子類必須定義更改此狀態的受保護方法,並定義哪種狀態對於此物件意味著被獲取或被釋放。

​ 假定這些條件之後,此類中的其他方法就可以實現所有排隊和阻塞機制。

​ 子類可以維護其他狀態字段,但只是為了獲得同步而只追蹤使用getstate()、setstate(int) 和compareandsetstate(int, int) 方法來操作以原子方式更新的 int 值。

應該將子類定義為非公共內部幫助器類,可用它們來實現其封閉類的同步屬性。類 abstractqueuedsynchronizer 沒有實現任何同步介面。

​ 而是定義了諸如 acquireinterruptibly(int) 之類的一些方法,在適當的時候可以通過具體的鎖和相關同步器來呼叫它們,以實現其公共方法。

​ 此類支援預設的獨佔 模式和共享 模式之一,或者二者都支援。處於獨佔模式下時,其他執行緒試圖獲取該鎖將無法取得成功。在共享模式下,多個執行緒獲取某個鎖可能(但不是一定)會獲得成功。此類並不「了解」這些不同,除了機械地意識到當在共享模式下成功獲取某一鎖時,下乙個等待執行緒(如果存在)也必須確定自己是否可以成功獲取該鎖。

處於不同模式下的等待執行緒可以共享相同的 fifo 佇列。通常,實現子類只支援其中一種模式,但兩種模式都可以在(例如)readwritelock 中發揮作用。只支援獨佔模式或者只支援共享模式的子類不必定義支援未使用模式的方法。

此類通過支援獨佔模式的子類定義了乙個巢狀的 abstractqueuedsynchronizer.conditionobject 類,可以將這個類用作 condition 實現。isheldexclusively() 方法將報告同步對於當前執行緒是否是獨佔的;使用當前 getstate() 值呼叫release(int) 方法則可以完全釋放此物件;如果給定儲存的狀態值,那麼 acquire(int) 方法可以將此物件最終恢復為它以前獲取的狀態。

​ 沒有別的 abstractqueuedsynchronizer 方法建立這樣的條件,因此,如果無法滿足此約束,則不要使用它。abstractqueuedsynchronizer.conditionobject 的行為當然取決於其同步器實現的語義。此類為內部佇列提供了檢查、檢測和監視方法,還為 condition 物件提供了類似方法。可以根據需要使用用於其同步

機制的 abstractqueuedsynchronizer 將這些方法匯出到類中。

此類的序列化只儲存維護狀態的基礎原子整數,因此已序列化的物件擁有空的執行緒佇列。需要可序列化的典型子類將定義乙個 readobject 方法,該方法在反序列化時將此物件恢復到某個已知初始狀態。

tryacquire(int)

tryrelease(int)

tryacquireshared(int)

tryreleaseshared(int)

isheldexclusively()

acquire:

while (!tryacquire(arg))

release:

if ((arg))

unblock the first queued thread;

5.深入剖析reentrantlock原始碼之非公平鎖的實現#

如何閱讀原始碼? 一段簡單的** 看構造 看類之間的關係,形成關係圖 看使用到的方法,並逐步理解,邊看

**邊看注釋 debug

6.深入剖析reentrantlock原始碼之公平鎖的實現#

6.1公平鎖與非公平鎖的區別

非公平鎖:只要有機會,就先嘗試搶占資源 公平鎖與非公平鎖

其實有點像在公廁上廁所。公平鎖遵守排隊的規則,只要前面有人在排隊,那麼剛進來的就老老實實排隊。而

非公平鎖就有點流氓,只要當前茅坑沒人,它就佔了那個茅坑,不管後面的人排了多久。

6.2原始碼解析

copy

非公平鎖的弊端

可能導致後面排隊等待的執行緒等不到相應的cpu資源,從而引起執行緒飢餓

7.掌控執行緒執行順序之多執行緒debug#

8.讀寫鎖特性及reentrantreadwritelock的使用#

特性:寫寫互斥、讀寫互斥、讀讀共享

鎖降級:寫執行緒獲取寫入鎖後可以獲取讀取鎖,然後釋放寫入鎖,這樣就從寫入鎖變成了讀取鎖,從而實現鎖

降級的特性。

9.原始碼探秘之aqs如何用單一int值表示讀寫兩種狀態#

10.深入剖析reentrantreadwritelock之讀鎖原始碼實現#

int 是32位,將其拆分成兩個無符號short

高位表示讀鎖     低位表示寫鎖

0000000000000000  0000000000000000

兩種鎖的最大次數均為65535也即是2的16次方減去1

讀鎖: 每次都從當前的狀態加上65536

0000000000000000  0000000000000000

0000000000000001  0000000000000000

0000000000000001  0000000000000000

0000000000000001  0000000000000000

0000000000000010  0000000000000000

獲取讀鎖個數,將state整個無符號右移16位就可得出讀鎖的個數

0000000000000001

寫鎖:每次都直接加1

0000000000000000  0000000000000000

0000000000000000  0000000000000001

0000000000000000  0000000000000001

獲取寫鎖的個數

0000000000000000  0000000000000001

0000000000000000  1111111111111111

0000000000000000  0000000000000001

11. 深入剖析reentrantreadwritelock之寫鎖原始碼實現#

0000000000000000 0000000000000001

0000000000000000 111111111111111111

0000000000000000 0000000000000001

12.鎖降級詳解#

鎖降級:寫執行緒獲取寫入鎖後可以獲取讀取鎖,然後釋放寫入鎖,這樣就從寫入鎖變成了讀取鎖,從而實現鎖

降級的特性。

注意點:鎖降級之後,寫鎖並不會直接降級成讀鎖,不會隨著讀鎖的釋放而釋放,因此需要顯式地釋放寫鎖

12.1是否有鎖公升級?

在reentrantreadwritelock裡面,不存在鎖公升級這一說法

鎖降級的應用場景

用於對資料比較敏感,需要在對資料修改之後,獲取到修改後的值,並進行接下來的其他操作

13.stampedlock原理及使用#

1.8之前,鎖已經那麼多了,為什麼還要有stampedlock?

一般應用,都是讀多寫少,reentrantreadwritelock 因讀寫互斥,故讀時阻塞寫,因而效能上上不去。可能

會使寫執行緒飢餓

13.1 stampedlock的特點

所有獲取鎖的方法,都返回乙個郵戳(stamp),stamp為0表示獲取失敗,其餘都表示成功; 所有釋放鎖的

方法,都需要乙個郵戳(stamp),這個stamp必須是和成功獲取鎖時得到的stamp一致; stampedlock是

不可重入的;(如果乙個執行緒已經持有了寫鎖,再去獲取寫鎖的話就會造成死鎖) 支援鎖公升級跟鎖降級 可

以樂觀讀也可以悲觀讀 使用有限次自旋,增加鎖獲得的機率,避免上下文切換帶來的開銷 樂觀讀不阻塞寫

操作,悲觀讀,阻塞寫得操作

13.2 stampedlock的優點

相比於reentrantreadwritelock,吞吐量大幅提公升

13.13 stampedlock的缺點

api相對複雜,容易用錯 內部實現相比於reentrantreadwritelock複雜得多

stampedlock的原理

每次獲取鎖的時候,都會返回乙個郵戳(stamp),相當於mysql裡的version欄位 釋放鎖的時候,再根據之

前的獲得的郵戳,去進行鎖釋放

使用stampedlock注意點

如果使用樂觀讀,一定要判斷返回的郵戳是否是一開始獲得到的,如果不是,要去獲取悲觀讀鎖,再次去讀取

悲觀鎖與樂觀鎖以及樂觀鎖的實現

總是假設最壞的情況,每次去拿資料的時候都認為別人會修改,所以每 次在拿資料的時候都會上鎖,這樣別人想拿這個資料就會阻塞直到它拿到鎖。傳 統的關係型資料庫裡邊就用到了很多這種鎖機制,比如行鎖,表鎖等,讀鎖,寫 鎖等,都是在做操作之前先上鎖。顧名思義,就是很樂觀,每次去拿資料的時候都認為別人不會修改,所...

事務,以及與鎖的區別

1.基本概念 事務,一般是指要做的或所做的事情。在計算機術語中是指訪問並可能更新資料庫中各種資料項的乙個程式執行單元 unit 2 特性 事務應該具有4個屬性 原子性 一致性 隔離性 永續性。這四個屬性通常稱為acid特性。原子性 atomicity 乙個事務是乙個不可分割的工作單位,事務中包括的諸...

Oracle表的分類以及相關引數的詳解

oracle中有如下幾種型別的表 1 堆組織表 heap organized tables 常用的表型別,以堆的方式管理,當增加資料時,將使用段中第乙個適合資料大小的空閒空間 當刪除資料時,留下的空間允許以後的dml操作重用。2 索引組織表 表儲存在索引結構中,利用行本身排序儲存。在堆中,資料可能被...