亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java并發J.U.C之AQS:CLH同步隊列的示例分析

發布時間:2021-09-09 11:28:22 來源:億速云 閱讀:141 作者:小新 欄目:編程語言

小編給大家分享一下Java并發J.U.C之AQS:CLH同步隊列的示例分析,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

CLH同步隊列是一個FIFO雙向隊列,AQS依賴它來完成同步狀態的管理,當前線程如果獲取同步狀態失敗時,AQS則會將當前線程已經等待狀態等信息構造成一個節點(Node)并將其加入到CLH同步隊列,同時會阻塞當前線程,當同步狀態釋放時,會把首節點喚醒(公平鎖),使其再次嘗試獲取同步狀態。

在CLH同步隊列中,一個節點表示一個線程,它保存著線程的引用(thread)、狀態(waitStatus)、前驅節點(prev)、后繼節點(next),其定義如下:

static final class Node {
 /** 共享 */
 static final Node SHARED = new Node();

 /** 獨占 */
 static final Node EXCLUSIVE = null;

 /**
 * 因為超時或者中斷,節點會被設置為取消狀態,被取消的節點時不會參與到競爭中的,他會一直保持取消狀態不會轉變為其他狀態;
 */
 static final int CANCELLED = 1;

 /**
 * 后繼節點的線程處于等待狀態,而當前節點的線程如果釋放了同步狀態或者被取消,將會通知后繼節點,使后繼節點的線程得以運行
 */
 static final int SIGNAL = -1;

 /**
 * 節點在等待隊列中,節點線程等待在Condition上,當其他線程對Condition調用了signal()后,改節點將會從等待隊列中轉移到同步隊列中,加入到同步狀態的獲取中
 */
 static final int CONDITION = -2;

 /**
 * 表示下一次共享式同步狀態獲取將會無條件地傳播下去
 */
 static final int PROPAGATE = -3;

 /** 等待狀態 */
 volatile int waitStatus;

 /** 前驅節點 */
 volatile Node prev;

 /** 后繼節點 */
 volatile Node next;

 /** 獲取同步狀態的線程 */
 volatile Thread thread;

 Node nextWaiter;

 final boolean isShared() {
 return nextWaiter == SHARED;
 }

 final Node predecessor() throws NullPointerException {
 Node p = prev;
 if (p == null)
 throw new NullPointerException();
 else
 return p;
 }

 Node() {
 }

 Node(Thread thread, Node mode) {
 this.nextWaiter = mode;
 this.thread = thread;
 }

 Node(Thread thread, int waitStatus) {
 this.waitStatus = waitStatus;
 this.thread = thread;
 }
}

CLH同步隊列結構圖如下:

Java并發J.U.C之AQS:CLH同步隊列的示例分析

入列

學了數據結構的我們,CLH隊列入列是再簡單不過了,無非就是tail指向新節點、新節點的prev指向當前最后的節點,當前最后一個節點的next指向當前節點。代碼我們可以看看addWaiter(Node node)方法:

 private Node addWaiter(Node mode) {
 //新建Node
 Node node = new Node(Thread.currentThread(), mode);
 //快速嘗試添加尾節點
 Node pred = tail;
 if (pred != null) {
 node.prev = pred;
 //CAS設置尾節點
 if (compareAndSetTail(pred, node)) {
 pred.next = node;
 return node;
 }
 }
 //多次嘗試
 enq(node);
 return node;
 }

addWaiter(Node node)先通過快速嘗試設置尾節點,如果失敗,則調用enq(Node node)方法設置尾節點

 private Node enq(final Node node) {
 //多次嘗試,直到成功為止
 for (;;) {
 Node t = tail;
 //tail不存在,設置為首節點
 if (t == null) {
 if (compareAndSetHead(new Node()))
 tail = head;
 } else {
 //設置為尾節點
 node.prev = t;
 if (compareAndSetTail(t, node)) {
 t.next = node;
 return t;
 }
 }
 }
 }

在上面代碼中,兩個方法都是通過一個CAS方法compareAndSetTail(Node expect, Node update)來設置尾節點,該方法可以確保節點是線程安全添加的。在enq(Node node)方法中,AQS通過“死循環”的方式來保證節點可以正確添加,只有成功添加后,當前線程才會從該方法返回,否則會一直執行下去。

過程圖如下:

Java并發J.U.C之AQS:CLH同步隊列的示例分析

出列

CLH同步隊列遵循FIFO,首節點的線程釋放同步狀態后,將會喚醒它的后繼節點(next),而后繼節點將會在獲取同步狀態成功時將自己設置為首節點,這個過程非常簡單,head執行該節點并斷開原首節點的next和當前節點的prev即可,注意在這個過程是不需要使用CAS來保證的,因為只有一個線程能夠成功獲取到同步狀態。過程圖如下:

Java并發J.U.C之AQS:CLH同步隊列的示例分析

以上是“Java并發J.U.C之AQS:CLH同步隊列的示例分析”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

河津市| 大洼县| 昂仁县| 东丽区| 垣曲县| 台南县| 新宁县| 罗山县| 阿克苏市| 永州市| 稷山县| 改则县| 德清县| 三原县| 库伦旗| 弋阳县| 阿拉尔市| 平江县| 荣昌县| 乐亭县| 靖宇县| 景德镇市| 文昌市| 华容县| 岳池县| 田阳县| 通海县| 正阳县| 公安县| 肇州县| 乌海市| 临西县| 盐亭县| 阿城市| 子洲县| 罗源县| 罗甸县| 黑河市| 自治县| 肥西县| 罗江县|