AQS框架基本流程

2021-08-28 23:55:00 字數 2877 閱讀 4420

我們先來看一下這個併發框架的原理,在之後的文章中我們將乙個乙個的分析那些有用的實現。

public final void acquire(int arg)
這個方法是獲取到資源的入口,首先他會嘗試來獲取arg個資源,如果沒有獲取成功,就會呼叫後面的方法將這次請求放到乙個同步佇列裡面,如果都失敗了,就會呼叫當前請求資源的中斷方法:

protected boolean tryacquire(int arg)
這個方法是讓具體的場景來實現的,我們接下來看一下如何新增到同步佇列當中:

addwaiter(node.exclusive)
首先建立了乙個waiter,裡面傳入了乙個引數:

static final node shared = new node();

//表示節點正在排它模式下等待的標記

static final node exclusive = null;

//等待狀態值,指示執行緒已取消

static final int cancelled = 1;

//等待狀態值,以指示後續執行緒需要解除安裝

static final int signal = -1;

//waitstatus值表示執行緒正在等待條件

static final int condition = -2;

//*等待狀態值,以指示下乙個獲取共享應該無條件地傳播

static final int propagate = -3;

我們建立的沒有給結點都有乙個他自己的狀態:

private node addwaiter(node mode) 

}//入隊

enq(node);

return node;

}

這個方法首先會根據請求資源的執行緒和模式建立要給同步結點,然後先建立他的前指標和尾節點的關係,這羊座的原因是,就算在入隊的時候失敗了,也可以通過同步佇列的尾節點遍歷整個同步佇列,最後一步就是入隊:

private node enq(final node node)  else }}

}

在這個方法中,首先獲取到了尾節點進行判斷這是否是新增的第乙個結點,如果是,直接通過cas操作將當前結點設定為頭節點,否則將當前結點通過cas操作設定為尾節點。這樣新的結點也入隊成功了,接下來他就帶著他需要請求的資源的個數進入下乙個方法:

final boolean acquirequeued(final node node, int arg) 

//檢查和更新未能獲取的節點的狀態。如果執行緒阻塞,返回true

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

//檢查是否中斷

parkandcheckinterrupt())

//標記當前執行緒被中斷

interrupted = true;

}} finally

}

首先通過自旋的方式檢查它的前結點是否是頭節點,如果是,讓他的前結點嘗試獲取資源,如果成功將當前結點設定為頭節點,並且返回。之後會根據前驅結點不同的狀態來做不同的處理是否需要掛起,如果需要掛起,那麼接下來就會先掛起當前執行緒,再檢查當前執行緒是否中斷:

private static boolean shouldparkafte***iledacquire(node pred, node node)  while (pred.waitstatus > 0);

pred.next = node;

} else

return false;

}

這個方法主要就是根據前驅結點不同的狀態值來做不同的處理。

private final boolean parkandcheckinterrupt()
這個方法就是掛起當前執行緒並判斷是否被中斷

private void cancelacquire(node node)  else  else 

node.next = node; // help gc

}}

刪除這個結點重新建立鍊錶之間的關係,再必要條件下喚醒它的繼承者:

private void unparksuccessor(node node) 

//喚醒當前執行緒

if (s != null)

locksupport.unpark(s.thread);

}

從當前結點開始找到第乙個狀態不為0的結點喚醒它。

接下來我們看一下符合釋放資源:

public void unlock()
直接呼叫的是同步框架的釋放方法,傳入的是釋放的資源的個數:

public final boolean release(int arg) 

return false;

}

首先會嘗試釋放資源,成功後會喚醒同步佇列中頭節點的繼承者:

protected boolean tryrelease(int arg)
釋放資源也是由具體的場景完成的:

private void unparksuccessor(node node) 

if (s != null)

locksupport.unpark(s.thread);

}

這個方法和之前的我們分析的方法是一樣的,我們就不具體看了。

再本章中我們只分析了一些主要的功能和一般流程,在後面的部落格中我們就要看具體的案例了。

AQS框架 談談對AQS框架的理解

aqs是乙個框架,基於它我們可以實現鎖和同步器,j.u.c.包中和很多鎖和同步器都是基於aqs實現的。使用aqs的方式通常不是讓鎖或同步器直接繼承aqs類,而是將aqs的子類作為鎖或同步器類的乙個輔助內部類,鎖或同步器的方法呼叫aqs子類物件的方法完成同步操作。來自網路 aqs中最重要的乙個字段就是...

spring mvc框架及基本流程

原創 傳統原生的jsp servlet在開發上過程上雖然簡單明瞭,jsp頁面傳遞資料到servlet,servlet整理資料 邏輯開發 或者從資料庫提取資料接著再 到jsp頁面上,但是其似乎只能止步於此,我們都知道我們request和response都依賴於url,當我們想要通過針對圍繞url進行程...

AQS框架實現類學習

author jinxindong 2016年11月1日 上午9 33 46 version v1.0 public class countdownlatchdemo static class worker extends thread public void run catch interrupt...