循序漸進理解AQS(2) AQS實現(未完)

2021-09-24 08:10:48 字數 2448 閱讀 4652

當執行緒獲取不到鎖時,aqs使用自旋和阻塞;

為了支援取消和超時操作,aqs對clh鎖的佇列進行了改進,增加顯式的鏈結指向前繼節點。如果直接前繼節點取消或者超時了,就尋找直接前繼的前繼;

由於釋放鎖需要通知後繼節點,aqs又增加了後繼節點鏈結進行優化(非必要)。

乙個同步器一般需要包含以下兩個操作:

獲取操作:acquire

阻塞呼叫的執行緒,直到同步狀態允許其繼續執行。

while (同步狀態獲取失敗) 

如果當前執行緒在佇列中,則移除

複製**

釋放操作:release

通過某種方式改變同步狀態,使得一或多個被acquire阻塞的執行緒繼續執行。

更新同步狀態

if (同步狀態許可乙個阻塞執行緒進行獲取)

複製**

因此我們可以從這兩個介面入手對原始碼進行解讀。另外需要補充說明的是,鎖的實現可以分為獨佔鎖和共享鎖,簡單起見,我們先聚焦獨享鎖的**實現,後續再看共享鎖的差異性。

acquire

public final void acquire(int arg) 

複製**

嘗試獲取鎖,獲取成功直接返回,不執行後續操作;

建立代表當前執行緒的節點,加入等待佇列;

自旋前繼節點狀態和阻塞執行緒

tryacquire

該方法檢查同步狀態state是否被許可,通俗來講就是看看是否能取到鎖。aqs中的實現只丟擲異常,所以基於aqs實現的鎖需要實現這個方法。

protected boolean tryacquire(int arg) 

複製**

node

當同步狀態沒有被許可時,需要在等待佇列中排隊,因此需要建立乙個代表該執行緒的節點加入佇列。下面我們來看節點的定義(刪減了部分目前無須關注的屬性)。

static final class node 

複製**

addwaiter

接下來需要把節點加入到等待佇列,整體思路是在隊尾插入節點。

入隊的時候需要考慮隊尾為空和不為空兩種情況,不過aqs的實現上是認為多數情況下隊尾都不為空,因此先按照隊尾不為空的方式嘗試快速入隊,如果失敗才用完整的入隊邏輯去入隊。

private node addwaiter(node mode) 

}enq(node);

return node;

}複製**

enq

初始化佇列的頭節點和尾節點:

在隊尾插入新節點,addwaiter中快速插入新節點的路徑就是這塊邏輯:

private node enq(final node node)  else }}

}複製**

acquirequeued

節點加入佇列後,接下來要做的事就是不斷檢查狀態是否可用。這裡實現的思路是先看前繼節點是否是頭節點(因為只有頭節點釋放鎖後,後繼節點才有可能獲取到鎖),然後再去檢查狀態;如果前繼不是頭節點,則修改前繼節點的狀態waitstatus = signal(表示後繼在等待喚醒),然後阻塞執行緒。

如果頭節點的後繼成功獲取到鎖了,則頭節點可以出隊了:

修改頭節點的指向到新節點(原頭節點的後繼);

新頭節點的前繼prev置為null(新頭節點的前繼就是原頭節點)

為了幫助gc**原頭節點,把原頭結點的後繼也置為null

final boolean acquirequeued(final node node, int arg) 

if (shouldparkafte***iledacquire(p, node) &&

parkandcheckinterrupt())

interrupted = true;

}} finally

}複製**

接下來是釋放鎖的操作,從節點入隊的流程來看,釋放鎖時除了需要修改同步狀態status,還需要喚醒後繼節點。

release

整個實現主要涉及下面三個事情:

public final boolean release(int arg) 

return

false;

}複製**

unparksuccessor

unparksuccessor(h)

private void unparksuccessor(node node) 

if (s != null)

locksupport.unpark(s.thread);

}複製**

《循序漸進學Spark》一第2章

第2章 spark 程式設計模型 與hadoop相比,spark最初為提公升效能而誕生。spark是hadoop mapreduce的演化和改進,並相容了一些資料庫的基本思想,可以說,spark一開始就站在hadoop與資料庫這兩個巨人的肩膀上。同時,spark依靠scala強大的函式式程式設計ac...

實現機器學習的循序漸進指南VI AdaBoost

目錄介紹 adaboost模型 弱分類器 權重更新 分類 結論與分析 可訪問 實現機器學習的循序漸進指南系列彙總,獲取本系列完成文章列表。adaboost 是boosting的一種方法,它基於多分類器組合可以在複雜環境中獲得更準確結果的原則。adaboost 模型由弱分類器,權重更新和分類組成。ad...

循序漸進的用js實現乙個bind

author thomaszhou 一般我們會直接使用bind函式,但是這次我們通過原生js來嘗試實現這個函式 bind 方法會建立乙個新函式。當這個新函式被呼叫時,bind 的第乙個引數將作為它執行時的 this,之後的一串行引數將會在傳遞的實參前傳入作為它的引數 由此我們可以首先得出 bind ...