国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

JUC之AQS框架

2019-11-10 22:53:00
字體:
供稿:網(wǎng)友

一、簡介

1. AQS

AQS是AbstractQueuedSynchronizer的簡寫,中文名應(yīng)該叫抽象隊(duì)列同步器(我給的名字,哈哈),出生于java 1.5

PRovides a framework for implementing blocking locks and related synchronizers (semaphores, events, etc) that rely on first-in-first-out (FIFO) wait queues. This class is designed to be a useful basis for most kinds of synchronizers that rely on a single atomic int value to represent state. Subclasses must define the protected methods that change this state, and which define what that state means in terms of this object being acquired or released. Given these, the other methods in this class carry out all queuing and blocking mechanics. Subclasses can maintain other state fields, but only the atomically updated int value manipulated using methods getState, setState and compareAndSetState is tracked with respect to synchronization. ——Java docs

翻開源碼,首先是一大段的注釋,然后可以看開AQS繼承自AbstractOwnableSynchronizer。當(dāng)你翻開AbstractOwnableSynchronizer時,還是先看到小段的說注釋。

A synchronizer that may be exclusively owned by a thread. This class provides a basis for creating locks and related synchronizers that may entail a notion of ownership. The AbstractOwnableSynchronizer class itself does not manage or use this information. However, subclasses and tools may use appropriately maintained values to help control and monitor access and provide diagnostics. ——Java docs

2. AOS

她生自Java 1.6

可以由線程以獨(dú)占方式擁有的同步器。此類為創(chuàng)建鎖和相關(guān)同步器(伴隨著所有權(quán)的概念)提供了基礎(chǔ)。AbstractOwnableSynchronizer 類本身不管理或使用此信息。但是,子類和工具可以使用適當(dāng)維護(hù)的值幫助控制和監(jiān)視訪問以及提供診斷。

簡言之,AOS(容我先如此縮寫吧)輸出的是一種概念,是一種創(chuàng)建獨(dú)占式同步器所有權(quán)的概念。她自身并沒有規(guī)范所有權(quán)的管理方式,更沒有用到這些信息(所有權(quán)的信息)。不過呢,可以幫其子類維護(hù)所有者信息。 可以你并不能理解上面這一小段話,不過沒關(guān)系接著看源碼就是了。 AOS提供兩個方法一個字段,外帶一個空構(gòu)造方法(可無視之)。

/** * The current owner of exclusive mode synchronization. */private transient Thread exclusiveOwnerThread; // transient表示該字段不需要序列化,因?yàn)锳OS實(shí)現(xiàn)了Serializableprotected final void setExclusiveOwnerThread(Thread thread) { exclusiveOwnerThread = thread;}protected final Thread getExclusiveOwnerThread() { return exclusiveOwnerThread;}

這下明白了吧,就是AOS啥都沒有就只維護(hù)一個東西——當(dāng)前誰持有獨(dú)占式同步器。因此咱們可以當(dāng)它不存在吧,繼續(xù)回到重點(diǎn)AQS。

You may also find the inherited methods from {@link AbstractOwnableSynchronizer} useful to keep track of the thread owning an exclusive synchronizer. You are encouraged to use them – this enables monitoring and diagnostic tools to assist users in determining which threads hold locks. – Java Docs

二、作用

Java Docs的注釋可以知道,AQS是一個框架,一個提供鎖或同步器依賴于FIFO等待隊(duì)列所必要的“基礎(chǔ)設(shè)施”的框架。Dong Lea之所以寫個抽象類的目的是為了簡化我們實(shí)現(xiàn)同步器的工作。

換句話說,

提供一個基于FIFO等待隊(duì)列,可以用于構(gòu)建鎖或者其他同步裝置的基礎(chǔ)框架。意在能夠成為實(shí)現(xiàn)大部分同步需求的基礎(chǔ)

AQS默認(rèn)提供了獨(dú)占式共享式兩種模式,JDK對應(yīng)的實(shí)現(xiàn)有ReentrantLockReentrantReadWriteLock。即除了提供acquire方法之外,還提供了acquireShare。帶shared都是共享模式相關(guān)操作,默認(rèn)則是獨(dú)占模式。

AQS到底提供了哪些便利呢: 1. 管理狀態(tài) 2. 實(shí)現(xiàn)了線程安全的CLH隊(duì)列 3. 實(shí)現(xiàn)了同步器公共方法 4. ConditionObject

三、原理

AQS自身就是一個Wait QueueCLH lock queue的變種,CLH隊(duì)列通常用于自旋鎖

The wait queue is a variant of a “CLH” (Craig, Landin, and Hagersten) lock queue. CLH locks are normally used for spinlocks. We instead use them for blocking synchronizers, but use the same basic tactic of holding some of the control information about a thread in the predecessor of its node.

我們知道Queue的底層實(shí)現(xiàn)是一個鏈表結(jié)構(gòu),我們也知道它可以是單鏈表,也可以是雙鏈表。AQS實(shí)現(xiàn)的是一個雙鏈表結(jié)構(gòu)。即每個節(jié)點(diǎn)都存儲了前驅(qū)和后繼兩個指針,而且Head節(jié)點(diǎn)是dummy節(jié)點(diǎn)。入隊(duì)則tail前驅(qū)一個節(jié)點(diǎn),再把新節(jié)點(diǎn)接入,然后接入tail節(jié)點(diǎn)。

AQS完全通過CAS解決多線程安全問題,即通過Unsafe完成的。具體可以自行閱讀AQS源碼,在最后幾個方法,非常簡單。

CAS : compareAndSet,Unsafe的CAS方法的語義是先與期望值進(jìn)行比較,若不相等返回false;若相等的話,則會把原值修改新值,再返回true。這個跟java.util.concurrent.atomic的原子類的CAS方法是一樣一樣的。

AQS的實(shí)現(xiàn)依賴LockSupport完成阻塞和喚醒,也正是LockSupport的引入使得AQS源碼閱讀起來邏輯上有點(diǎn)跳躍。不過沒關(guān)系,后面我們梳理Java Lock的時候,會把LockSupport重新拿出來看的。

什么是自旋鎖,如下示例實(shí)現(xiàn)的即是自旋鎖,即是循環(huán)等待信號量變成期望值后完成相關(guān)操作。

// 來自 AQS#doAcquireInterruptiblyprivate void doAcquireInterruptibly(int arg) throws InterruptedException { final Node node = addWaiter(Node.EXCLUSIVE); boolean failed = true; try { for (;;) { // 自旋鎖 final Node p = node.predecessor(); if (p == head && tryAcquire(arg)) { // 相當(dāng)于阻塞到信號量變成期望值 setHead(node); p.next = null; // help GC failed = false; return; } if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) throw new InterruptedException(); } } finally { if (failed) cancelAcquire(node); }}

除此之外,AQS提供一些與同步器業(yè)務(wù)相關(guān)的一些方法,如:acquire和release。另外還有一些與Queue監(jiān)控相關(guān)的方法。

AQS提供的所有方法的分類列表: 1. Queuing utilities 2. Utilities for various versions of acquire cancelAcquire 3. Main exported methods tryAcquire releaseShared 4. Queue inspection methods hasQueuedThreads 5. Instrumentation and monitoring methods getQueueLength 6. Interenal support methdos for Conditions isOnSyncQueue 7. Instrumentation methods for conditions owns 8. Internal methods addConditionWaiter 9. public methods 10. for interruptible waits, we need to track whether to throw InterruptedException,…. 11. Support for instrumentation isOwnedBy 12. CAS : unsafe

四、用法

AQS的用法,可以直接參考AQS的注釋,另外也可以參考ReentrantLock的寫法。 通過比外提供兩個方法acquirerelease的源碼可知,它們是通過調(diào)用對應(yīng)protected的try方法完成的。

public final void acquire(int arg) { if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt();}public final boolean release(int arg) { if (tryRelease(arg)) { Node h = head; if (h != null && h.waitStatus != 0) unparkSuccessor(h); return true; } return false;}

注釋指出了,繼承AQS需要實(shí)現(xiàn)下面五個方法,

tryAcquire(int arg) tryRelease(int arg) tryAcquireShared(int arg) tryReleaseShared(int arg) isHeldExclusively()

它們帶的int參數(shù),用來表示狀態(tài),如下面示例中,用了10表示鎖和釋放。 如你所知,前兩個是獨(dú)占式,中間兩個是共享式。最后是測試當(dāng)是同步器是否正被持有獨(dú)占鎖。即是已經(jīng)有線程持有這個排他鎖,且還未釋放。

下面是AQS注釋里提供的實(shí)現(xiàn)。

class Mutex implements Lock, java.io.Serializable { // Our internal helper class private static class Sync extends AbstractQueuedSynchronizer { // Report whether in locked state protected boolean isHeldExclusively() { return getState() == 1; } // Acquire the lock if state is zero public boolean tryAcquire(int acquires) { assert acquires == 1; // Otherwise unused if (compareAndSetState(0, 1)) { setExclusiveOwnerThread(Thread.currentThread()); return true; } return false; } // Release the lock by setting state to zero protected boolean tryRelease(int releases) { assert releases == 1; // Otherwise unused if (getState() == 0) throw new IllegalMonitorStateException(); setExclusiveOwnerThread(null); setState(0); return true; } // Provide a Condition Condition newCondition() { return new ConditionObject(); } // Deserialize properly private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { s.defaultReadObject(); setState(0); // reset to unlocked state } } // The sync object does all the hard work. We just forward to it. private final Sync sync = new Sync(); public void lock() { sync.acquire(1); } public boolean tryLock() { return sync.tryAcquire(1); } public void unlock() { sync.release(1); } public Condition newCondition() { return sync.newCondition(); } public boolean isLocked() { return sync.isHeldExclusively(); } public boolean hasQueuedThreads() { return sync.hasQueuedThreads(); } public void lockInterruptibly() throws InterruptedException { sync.acquireInterruptibly(1); } public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { return sync.tryAcquireNanos(1, unit.toNanos(timeout)); }}

發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 茶陵县| 庆阳市| 中江县| 昌邑市| 界首市| 九龙县| 四平市| 海伦市| 汶川县| 枣庄市| 剑河县| 南投市| 黔西县| 蓬安县| 安远县| 杭锦后旗| 荣成市| 大化| 全南县| 英山县| 九龙城区| 文登市| 阳山县| 玛多县| 郧西县| 镇远县| 南宁市| 鄢陵县| 新闻| 普兰店市| 乐至县| 诸城市| 韩城市| 色达县| 威海市| 揭阳市| 株洲市| 齐河县| 苗栗县| 金昌市| 广宁县|