您好,登錄后才能下訂單哦!
如何深入理解Java多線程與并發框中的隊列同步器AQS,針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。
一、 AbstractOwnableSynchronizer 抽象的、可擁有的同步器
源碼分析:
package java.util.concurrent.locks; /** * 可由線程獨占的同步器。 * 該類為創建鎖和相關的同步器提供了基礎,可能需要擁有所有權的概念。 * AbstractOwnableSynchronizer 類本身不管理或使用此信息。 * 但是,子類和工具可以使用適當維護的值來幫助控制和監視訪問并提供診斷。 * * @since 1.6 * @author Doug Lea */ public abstract class AbstractOwnableSynchronizer implements java.io.Serializable { /** 即使所有的字段都是短暫的(被禁止序列化的),也要使用 序列ID。*/ private static final long serialVersionUID = 3737899427754241961L; /** * 供子類使用的空的構造方法。 */ protected AbstractOwnableSynchronizer() { } /** * 獨占模式同步下的當前(線程)擁有者。(也就是當前獨占鎖的線程) */ private transient Thread exclusiveOwnerThread; /** * 設置 當前擁有獨占訪問的 線程。 * 空參數指示沒有線程擁有訪問權限。 * 此方法不另外施加任何同步化易失性 volatile 字段訪問。 * @param thread 所有者的線程(擁有當前獨占訪問權的線程) */ protected final void setExclusiveOwnerThread(Thread thread) { exclusiveOwnerThread = thread; } /** * 返回 setExclusiveOwnableThread(Thread thread) 方法最后設置的線程, * 如果從未設置,則返回 null。 * 此方法不另外施加任何同步化易失性 volatile 字段訪問。 * @return 所有者的線程(擁有當前獨占訪問權的線程) */ protected final Thread getExclusiveOwnerThread() { return exclusiveOwnerThread; } }
小結: 獨占、持有鎖的線程成員變量:Thread exclusiveOwnerThread setExclusiveOwnerThread(Thread thread) 設置獨占、持有鎖的線程成員變量 getExclusiveOwnerThread() 獲得獨占、持有鎖的線程成員變量
AbstractQueuedSynchronizer 簡介
提供了一個基于 FIFO隊列,可以用于構建鎖或者其他相關同步裝置的基礎框架。該 抽象隊列同步器(以下簡稱隊列同步器)利用了一個 private volatile int state來表示 同步狀態,期望它能夠成為實現大部分同步需求的基礎。使用的方法是繼承,子類通過繼承同步器并需要實現它的方法來管理其狀態,管理的方式就是通過類似 acquire獲取 和 release釋放 的方式來 操縱狀態。然而 多線程環境中對狀態的操縱必須確保原子性,因此子類對于狀態的把握,需要使用這個同步器提供的以下三個方法對狀態進行操作:
private volatile int state;
java.util.concurrent.locks.AbstractQueuedSynchronizer.getState()
java.util.concurrent.locks.AbstractQueuedSynchronizer.setState(int newState)
java.util.concurrent.locks.AbstractQueuedSynchronizer.compareAndSetState(int expect, int update)
1. 源碼分析:
/** * 返回同步狀態的當前值。 * 此操作具有易失性 volatile 讀取的內存語義。 * @return 當前 state 的值 */ protected final int getState() { return state; } // ------------------- 華麗的分割線 ------------------- /** * 設置同步狀態 state 的值。 * 此操作具有易失性 volatile 寫的內存語義。 * @param newState 狀態 state 的新值 */ protected final void setState(int newState) { state = newState; } // ------------------- 華麗的分割線 ------------------- /** * 如果當前狀態值等于預期值,則以原子方式將同步狀態設置為給定的更新值。 * 此操作具有易失性 volatile 讀取和寫入的內存語義。 * * @param expect 期望的值 * @param update 新值 * @return 如果成功則為 true 。 錯誤返回表示實際值不等于預期值的指示。 */ protected final Boolean compareAndSetState(int expect, int update) { // See below for intrinsics setup to support this return unsafe.compareAndSwapint(this, stateOffset, expect, update); }
2. FIFO 隊列 (類似雙向鏈表)
同步器的開始提到了其實現依賴于一個 FIFO 隊列,那么隊列中的 元素節點Node 就是保存著 線程引用 和 線程狀態 的 容器,每個線程對同步器的訪問,都可以看做是隊列中的一個節點Node。Node的主要包含以下成員變量:
static final class Node { /** 作為標記表示節點正在 共享模式 中等待 */ static final Node SHARED = new Node(); /** 作為標記表示節點正在 獨占模式 下等待 */ static final Node EXCLUSIVE = null; int waitStatus; volatile Node prev; volatile Node next; volatile Thread thread; volatile Node nextWaiter; final Boolean isShared() { return nextWaiter == SHARED; } }
關于如何深入理解Java多線程與并發框中的隊列同步器AQS問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。