日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

同步类的基础AbstractQueuedSynchronizer(AQS)

發布時間:2024/2/28 编程问答 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 同步类的基础AbstractQueuedSynchronizer(AQS) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

同步類的基礎AbstractQueuedSynchronizer(AQS)

我們之前介紹了很多同步類,比如ReentrantLock,Semaphore, CountDownLatch, ReentrantReadWriteLock,FutureTask等。

AQS封裝了實現同步器時設計的大量細節問題。他提供了FIFO的wait queues并且提供了一個int型的state表示當前的狀態。

根據JDK的說明,并不推薦我們直接使用AQS,我們通常需要構建一個內部類來繼承AQS并按照需要重寫下面幾個方法:

  • tryAcquire
  • tryRelease
  • tryAcquireShared
  • tryReleaseShared
  • isHeldExclusively

在這些方法中,我們需要調用getState, setState 或者 compareAndSetState這三種方法來改變state值。

上面的方法提到了兩種操作,獨占操作(如:ReentrantLock)和共享操作(如:Semaphore,CountdownLatch)。

兩種的區別在于同一時刻能否有多個線程同時獲取到同步狀態。

比如我們運行同時多個線程去讀,但是通知只允許一個線程去寫,那么這里的讀鎖就是共享操作,而寫鎖就是獨占操作。

在基于QAS構建的同步類中,最基本的操作就是獲取操作和釋放操作。而這個state就表示的是這些獲取和釋放操作所依賴的值。

State是一個int值,你可以使用它來表示任何狀態,比如ReentrantLock用它來表示所有者線程重復獲取該鎖的次數。Semaphore用它來表示剩余的許可量,而FutureTask用它來表示任務的狀態(開始,運行,完成或者取消)。當然你還可以自定義額外的狀態變量來表示其他的信息。

下的偽代碼表示的是AQS中獲取和釋放操作的形式:

Acquire:while (!tryAcquire(arg)) {enqueue thread if it is not already queued;possibly block current thread;}Release:if (tryRelease(arg))unblock the first queued thread;

獲取操作,首先判斷當前狀態是否允許獲取操作,如果如果不允許,則將當前的線程入Queue,并且有可能阻塞當前線程。

釋放操作,則先判斷是否運行釋放操作,如果允許,則解除queue中的thread,并運行。

我們看一個具體的實現:

public class AQSUsage {private final Sync sync= new Sync();private class Sync extends AbstractQueuedSynchronizer{protected int tryAcquireShared(int ignored){return (getState() ==1 )? 1: -1;}protected boolean tryReleaseShared(int ignored){setState(1);return true;}}public void release() {sync.releaseShared(0);}public void acquire() throws InterruptedException {sync.acquireSharedInterruptibly(0);} }

上面的例子中,我們定義了一個內部類Sync,在這個類中我們實現了tryAcquireShared和tryReleaseShared兩個方法,在這兩個方法中我們判斷并設置了state的值。

sync.releaseShared和sync.acquireSharedInterruptibly會分別調用tryAcquireShared和tryReleaseShared方法。

前面我們也提到了很多同步類都是使用AQS來實現的,我們可以再看看其他標準同步類中tryAcquire的實現。

首先看下ReentrantLock:

final boolean tryAcquire(int acquires) {final Thread current = Thread.currentThread();int c = getState();if (c == 0) {if (compareAndSetState(0, acquires)) {setExclusiveOwnerThread(current);return true;}}else if (current == getExclusiveOwnerThread()) {int nextc = c + acquires;if (nextc < 0) // overflowthrow new Error("Maximum lock count exceeded");setState(nextc);return true;}return false;}

ReentrantLock只支持獨占鎖。所以它需要實現tryAcquire方法。除此之外它還維護了一個owner變量來保存當前所有者線程的標志符,從而來實現可重入鎖。

我們再看下Semaphore和CountDownLatch的實現,因為他們是共享操作,所以需要實現tryAcqureShared方法:

final int tryAcquireShared(int acquires) {for (;;) {int available = getState();int remaining = available - acquires;if (remaining < 0 ||compareAndSetState(available, remaining))return remaining;}}

本文的例子請參考https://github.com/ddean2009/learn-java-concurrency/tree/master/AQS

更多精彩內容且看:

  • 區塊鏈從入門到放棄系列教程-涵蓋密碼學,超級賬本,以太坊,Libra,比特幣等持續更新
  • Spring Boot 2.X系列教程:七天從無到有掌握Spring Boot-持續更新
  • Spring 5.X系列教程:滿足你對Spring5的一切想象-持續更新
  • java程序員從小工到專家成神之路(2020版)-持續更新中,附詳細文章教程

更多內容請訪問 flydean的博客

總結

以上是生活随笔為你收集整理的同步类的基础AbstractQueuedSynchronizer(AQS)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。