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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

unit类型是什么?_面试官虚晃一枪:项目中有用过锁吗?能解释一下什么是AQS?...

發(fā)布時間:2024/9/27 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 unit类型是什么?_面试官虚晃一枪:项目中有用过锁吗?能解释一下什么是AQS?... 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

1 前言

鎖是用來控制多個線程訪問共享資源的方式,一般來說,一個鎖能防止多個線程同時訪問共享資源(但是有些鎖可以允許多個線程并發(fā)的訪問共享資源,如讀寫鎖)。在以前,Java程序是靠synchronized來實現(xiàn)鎖功能的,而在Java SE 5之后,并發(fā)包中新增了Lock接口(以及相關(guān)實現(xiàn)類)用來實現(xiàn)鎖功能,他提供了與synchronized關(guān)鍵字類似的同步功能,只是在使用時需要顯式的獲取鎖和釋放鎖,雖然它缺少了synchronized提供的隱式獲取釋放鎖的便捷性,但是卻擁有了鎖獲取和釋放的可操作性、可中斷的獲取鎖以及超時獲取鎖等多種synchronized關(guān)鍵字不具備的同步特性。很多鎖都通過實現(xiàn)Lock接口來完成對鎖的操作,比如可重入鎖(ReentrantLock)、前一張講的Redisson分布式鎖等,而Lock接口的實現(xiàn),基本是都是通過聚合了一個同步器的子類來完成線程訪問控制的,而同步器,就是我們常說的AQS(AbstractQueuedSynchronizer),也是今天要記錄的內(nèi)容。

2 什么是AQS

AQS(隊列同步器AbstractQueuedSynchronizer)是用來構(gòu)建鎖或者其他同步組件的基礎(chǔ)框架,它使用了一個int成員變量來表示同步狀態(tài),通過內(nèi)置的FIFO隊列來完成資源獲取線程的排隊工作。

如上圖所示,同步器的主要使用方式是繼承,子類通過繼承同步器并實現(xiàn)它的抽象方法來管理同步狀態(tài),在抽象方法的實現(xiàn)過程中免不了要對同步狀態(tài)進行修改,這時就需要使用同步器提供的3個方法來進行操作:

1、getState():獲取當前同步狀態(tài)

2、setState():設(shè)置當前同步狀態(tài)

3、compareAndSetState(int expect, int update):通過CAS設(shè)置當前狀態(tài),該方法能保證狀態(tài)設(shè)置的原子性

子類推薦被定義為自定義同步組件的靜態(tài)內(nèi)部類,同步器自身沒有實現(xiàn)任何同步接口,它僅僅是定義了若干同步狀態(tài)獲取和釋放的方法來供自定義同步組件使用。同步器既可以支持獨占式獲取同步狀態(tài)(單個線程獲取鎖),也可以支持共享式獲取同步狀態(tài)(多個線程獲取到鎖),這樣就可以方便實現(xiàn)不同類型的同步組件(如上圖所示的可重入鎖:ReentrantLock、可重入讀寫鎖:ReentrantReadWriteLock、計數(shù)器:CountDownLatch等等)

3 同步器可重寫的方法

以下代碼為可重入鎖繼承同步器后重寫的方法:

  • protected boolean tryAcquire(int acquires):獨占式獲取同步鎖狀態(tài),實現(xiàn)該方法需要查詢當前狀態(tài)并判斷同步狀態(tài)是否符合預期,然后再進行CAS設(shè)置同步狀態(tài)。
/*** 非公平鎖*/static final class NonfairSync extends Sync {private static final long serialVersionUID = 7316153563782823691L;/*** Performs lock. Try immediate barge, backing up to normal* acquire on failure.*/final void lock() {if (compareAndSetState(0, 1))setExclusiveOwnerThread(Thread.currentThread());elseacquire(1);}protected final boolean tryAcquire(int acquires) {// nonfairTryAcquire方法和下面的公平鎖方法除了判斷是否在隊列首位之外沒有不同return nonfairTryAcquire(acquires);}}/*** 公平鎖*/static final class FairSync extends Sync {private static final long serialVersionUID = -3000897897090466540L;final void lock() {acquire(1);}/*** Fair version of tryAcquire. Don't grant access unless* recursive call or no waiters or is first.*/protected final boolean tryAcquire(int acquires) {final Thread current = Thread.currentThread();// 獲取當前同步狀態(tài)int c = getState();// 判斷是否符合預期if (c == 0) {// 判斷是否在隊列首位并且CAS設(shè)置當前狀態(tài)成功if (!hasQueuedPredecessors() &&compareAndSetState(0, acquires)) {setExclusiveOwnerThread(current);return true;}}else if (current == getExclusiveOwnerThread()) {int nextc = c + acquires;if (nextc < 0)throw new Error("Maximum lock count exceeded");setState(nextc);return true;}return false;}}
  • protected boolean tryRelease(int acquires):獨占式釋放同步鎖狀態(tài),等待獲取同步狀態(tài)的線程將有機會獲取同步狀態(tài)。
protected final boolean tryRelease(int releases) {int c = getState() - releases;if (Thread.currentThread() != getExclusiveOwnerThread())throw new IllegalMonitorStateException();boolean free = false;if (c == 0) {free = true;setExclusiveOwnerThread(null);}setState(c);return free;}
  • protected boolean isHeldExclusively():當前同步器是否在獨占模式下被線程占用,一般該方法表示是否被當前線程鎖獨占。
protected final boolean isHeldExclusively() {// While we must in general read state before owner,// we don't need to do so to check if current thread is ownerreturn getExclusiveOwnerThread() == Thread.currentThread();}

以下代碼為讀寫鎖繼承同步器后重寫的方法:

  • protected int tryAcquireShared(int arg):共享式獲取同步狀態(tài),返回大于0的值,表示獲取鎖成功,反之獲取鎖失敗。
protected final int tryAcquireShared(int unused) {Thread current = Thread.currentThread();// 獲取當前同步狀態(tài)int c = getState();// 如果有線程持有寫鎖,則返回-1if (exclusiveCount(c) != 0 &&getExclusiveOwnerThread() != current)return -1;// 獲取持有鎖的線程數(shù)int r = sharedCount(c);// 判斷是否阻塞,判斷線程數(shù)量,判斷CAS設(shè)置是否成功if (!readerShouldBlock() &&r < MAX_COUNT &&compareAndSetState(c, c + SHARED_UNIT)) {// 當前線程是第一個獲取到鎖的線程if (r == 0) {firstReader = current;firstReaderHoldCount = 1;// 否則就++} else if (firstReader == current) {firstReaderHoldCount++;} else { HoldCounter rh = cachedHoldCounter;if (rh == null || rh.tid != getThreadId(current))cachedHoldCounter = rh = readHolds.get();else if (rh.count == 0)readHolds.set(rh);rh.count++;}return 1;}// 死循環(huán)去獲取鎖return fullTryAcquireShared(current);}
  • protected boolean tryReleaseShared(int arg):共享式釋放同步狀態(tài)。
protected final boolean tryReleaseShared(int unused) {Thread current = Thread.currentThread();// 對應(yīng)上面獲取鎖來讀就好了if (firstReader == current) {// assert firstReaderHoldCount > 0;if (firstReaderHoldCount == 1)firstReader = null;elsefirstReaderHoldCount--;} else {HoldCounter rh = cachedHoldCounter;if (rh == null || rh.tid != getThreadId(current))rh = readHolds.get();int count = rh.count;if (count <= 1) {readHolds.remove();if (count <= 0)throw unmatchedUnlockException();}--rh.count;}for (;;) {int c = getState();int nextc = c - SHARED_UNIT;if (compareAndSetState(c, nextc))// Releasing the read lock has no effect on readers,// but it may allow waiting writers to proceed if// both read and write locks are now free.return nextc == 0;}}

上面例子,因為讀寫鎖是共享鎖,可重入鎖是獨占鎖,而同步器對于共享鎖和獨占鎖都提供了可重寫的方法來獲取鎖或者釋放鎖,所以分了兩個例子來寫。

4 同步器提供的模版方法

  • void acquire(int arg):獨占式獲取同步狀態(tài),如果當前線程獲取同步狀態(tài)成功則返回,否則,將會進入同步隊列等待。
public final void acquire(int arg) {// 如果獲取鎖失敗,則加入同步隊列,如果加入同步隊列成功則自旋阻塞喚醒來不斷的嘗試獲取鎖,直到線程被中斷或獲取到鎖if (!tryAcquire(arg) &&acquireQueued(addWaiter(Node.EXCLUSIVE), arg))selfInterrupt();}
  • void acquireInterruptibly(int arg):與上面acquire相似,但是當前方法如果在獲取鎖的過程中線程中斷會拋出InterruptedException并返回。
public final void acquireInterruptibly(int arg) throws InterruptedException {// 線程中斷拋出異常if (Thread.interrupted())throw new InterruptedException();// 如果沒有獲取到鎖if (!tryAcquire(arg))// 不斷自旋嘗試獲取鎖doAcquireInterruptibly(arg);}
  • boolean tryAcquireNanos(int arg, long nanosTimeout):在acquireInterruptibly()方法的基礎(chǔ)上增加了超時時間,如果在超時時間內(nèi)獲取到了鎖,則返回true,否則返回false。
public final boolean tryAcquireNanos(int arg, long nanosTimeout) throws InterruptedException {// 中斷拋異常if (Thread.interrupted())throw new InterruptedException();// 相應(yīng)時間內(nèi)不斷獲取鎖,超時返回falsereturn tryAcquire(arg) ||doAcquireNanos(arg, nanosTimeout);}
  • void acquireShared(int arg):共享式的獲取同步狀態(tài),如果當前線程未獲取到同步狀態(tài),則會進入同步隊列等待,與獨占鎖的主要區(qū)別是在同一時刻可以有多少個線程獲取到同步狀態(tài)。
public final void acquireShared(int arg) {// 如果獲取鎖失敗,則不斷自旋嘗試獲取鎖,tryAcquireShared方法在上面有講if (tryAcquireShared(arg) < 0)doAcquireShared(arg);}
  • void acquireSharedInterruptibly(int arg):與acquireShared方法相似,只是如果線程中斷,當前方法會拋出異常。
public final void acquireSharedInterruptibly(int arg) throws InterruptedException {// 中斷拋出異常if (Thread.interrupted())throw new InterruptedException();// 如果獲取鎖失敗,則不斷自旋嘗試獲取鎖if (tryAcquireShared(arg) < 0)doAcquireSharedInterruptibly(arg);}
  • boolean tryAcquireSharedNanos(int arg, long nanosTimeout):在acquireSharedInterruptibly方法的基礎(chǔ)上增加了超時時間。
public final boolean tryAcquireSharedNanos(int arg, long nanosTimeout) throws InterruptedException {// 中斷拋出異常if (Thread.interrupted())throw new InterruptedException();// 在超時時間內(nèi)如果獲取鎖失敗,則不斷自旋嘗試獲取鎖return tryAcquireShared(arg) >= 0 ||doAcquireSharedNanos(arg, nanosTimeout);}
  • boolean release(int arg):獨占式釋放同步狀態(tài),該方法在釋放同步狀態(tài)之后,會將隊列中的第一個節(jié)點包含的線程喚醒。
public final boolean release(int arg) {// 如果獲取鎖成功if (tryRelease(arg)) {Node h = head;if (h != null && h.waitStatus != 0)// 喚醒第一個節(jié)點的線程unparkSuccessor(h);return true;}return false;}
  • boolean releaseShared(int arg):共享式釋放同步狀態(tài)。
public final boolean releaseShared(int arg) {// 如果釋放鎖成功if (tryReleaseShared(arg)) {// 喚醒線程doReleaseShared();return true;}return false;}
  • Collection getQueuedThreads():獲取等待在同步隊列上的線程集合。
public final Collection<Thread> getQueuedThreads() {ArrayList<Thread> list = new ArrayList<Thread>();for (Node p = tail; p != null; p = p.prev) {Thread t = p.thread;if (t != null)list.add(t);}return list;}

同步器提供的模板方法基本是分為3類:

  • 獨占式獲取與釋放同步狀態(tài)
  • 共享式獲取與釋放同步狀態(tài)
  • 查詢同步隊列中的等待線程集合

5 根據(jù)同步器自定義同步組件

上面介紹了一些AQS提供的可重寫方法和模板方法,接下來我們自定義一個獨占鎖(在同一時刻只有一個線程能獲取鎖,其他獲取鎖的線程只能處于同步隊列中,當獲取到鎖的線程釋放鎖之后,后面的線程才能夠獲取鎖)

public class ExclusiveLock implements Lock {/*** 自定義同步器*/private static class Sync extends AbstractQueuedSynchronizer{// 判斷是否處于占用狀態(tài)@Overrideprotected boolean isHeldExclusively(){return getState() == 1;}// 加鎖@Overrideprotected boolean tryAcquire(int arg) {// 通過CAS設(shè)置同步狀態(tài)(設(shè)置成功返回true 設(shè)置失敗返回false)if (compareAndSetState(0, 1)){setExclusiveOwnerThread(Thread.currentThread());return true;}return false;}// 釋放鎖@SneakyThrows@Overrideprotected boolean tryRelease(int arg) {// 如果同步狀態(tài)為未獲取鎖,則拋出異常,沒有線程獲取到鎖,不能釋放鎖if (getState() == 0){throw new IllegalAccessException();}// 釋放鎖setExclusiveOwnerThread(null);setState(0);return true;}// 返回一個Condition,每個Condition都包含一個Condition隊列protected Condition newCondition() {return new ConditionObject();}}private final Sync sync = new Sync();@Overridepublic void lock() {// 獨占式加鎖sync.acquire(1);}@Overridepublic void lockInterruptibly() throws InterruptedException {// 加鎖線程中斷拋出異常,否則自旋加鎖sync.acquireInterruptibly(1);}@Overridepublic boolean tryLock() {// 加鎖成功返回true,否則設(shè)置占用排它鎖的線程是當前線程return sync.tryAcquire(1);}@Overridepublic boolean tryLock(long time, TimeUnit unit) throws InterruptedException {// 加鎖線程中斷拋出異常,否則在有效時間內(nèi)嘗試自旋加鎖return sync.tryAcquireSharedNanos(1, unit.toNanos(time));}@Overridepublic void unlock() {// 釋放鎖sync.release(1);}@Overridepublic Condition newCondition() {// 返回Conditionreturn sync.newCondition();} }

如上代碼,我們自定義了一個獨占鎖,它在同一時刻只允許一個線程占有鎖。sync內(nèi)部類繼承了同步器并實現(xiàn)了獨占式獲取和釋放同步狀態(tài)。在tryAcquire(int arg)方法中,如果通過CAS設(shè)置成功,則代表獲取了同步狀態(tài),而在tryRelease(int arg)方法中只是將同步狀態(tài)重制為0。用戶在使用ExclusiveLock時并不會直接和內(nèi)部同步器打交道,而是調(diào)用ExclusiveLock提供的方法即可,如加鎖調(diào)用lock()方法,如果獲取鎖失敗則會被加入同步隊列中,釋放鎖調(diào)用unlock()方法,如果沒有線程獲取鎖的時候釋放鎖會拋出異常,還可以按指定時間嘗試獲取鎖等等。

結(jié)尾

本來想把同步器實現(xiàn)原理也寫一些的,結(jié)果看了一下篇幅好想有些許長,那就分兩篇來寫把,如果看完感覺有幫助的,請幫忙點個贊,謝謝各位,有緣下篇文章再見!

總結(jié)

以上是生活随笔為你收集整理的unit类型是什么?_面试官虚晃一枪:项目中有用过锁吗?能解释一下什么是AQS?...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 久久免费片 | 二区久久| 公交上高潮的丁芷晴 | 91网站免费看 | 日本免费黄网站 | 欧美人和黑人牲交网站上线 | 五月天色综合 | 日本少妇xxxxxx | 中文字幕免费高清网站 | 天天爽夜夜爽 | 桃谷绘里香在线播放 | juliaannxxxxx高清 黄页网站在线播放 | 欧美综合视频在线 | 欧美性大战久久久久久久蜜桃 | 午夜性福利视频 | 国产精品一区二区av | 日韩高清免费观看 | 日本视频黄 | 欧美三级黄色大片 | 久久午夜国产 | 最新天堂av | 欧美aa级 | 国内偷拍av | 国产午夜不卡 | 最色网站| 亚洲人人夜夜澡人人爽 | 欧美高清一区二区 | 国产网站免费 | 亚洲三级图片 | 欧美成年人在线观看 | 亚洲精品国产精品国自产网站 | 欧美黄色大片在线观看 | 久久网站视频 | 天天爽天天爽 | 国产精品无码天天爽视频 | 国产网红在线观看 | 欧美激情免费在线观看 | 久操欧美 | 免费成人高清 | 红猫大本营在线观看的 | 每日在线更新av | 69视频在线免费观看 | 亚洲三级网站 | 国产精品后入内射日本在线观看 | 男人添女人囗交视频 | 国产精品后入内射日本在线观看 | 日韩一级精品 | 国产视频导航 | 久久传媒 | 青青草综合在线 | 国产欧美精品 | 伊人久久大 | 亚洲天堂岛 | 好吊色欧美一区二区三区视频 | 九九热精品视频 | 99无码熟妇丰满人妻啪啪 | 国产在线免费观看 | 免费毛片大全 | yw在线观看 | 久久夜色精品国产欧美乱极品 | 日韩色资源 | 国产三级一区二区三区 | 美女三级视频 | 欧美精品色哟哟 | 在线日韩视频 | 国产最新自拍视频 | 中国 免费 av| 日韩中文字幕精品视频 | 国产精品91一区二区 | 潘金莲裸体一级淫片视频 | 亚洲成人激情在线 | 色婷婷av一区二区三区麻豆综合 | 又大又长粗又爽又黄少妇视频 | 国产成人久久精品 | 国产极品91 | av黄在线| 亚洲国产精品久久久久婷婷老年 | 亚洲男人天堂2024 | 成人午夜毛片 | 奇米久久久 | 中文字幕在线一区二区三区 | 国产精品极品 | 欧美破处大片 | wwwxxxx国产| 国产国语videosex另类 | 先锋影音一区二区三区 | 桃色综合网| 国产国语亲子伦亲子 | 夜夜爽www| 国产肥熟 | 免费观看一级一片 | 国产精品五区 | 日韩精品视频免费在线观看 | 交做爰xxxⅹ性爽 | 性爱视频在线免费 | 国产91精品久久久久久久网曝门 | 国产精品一区二区无线 | 成人www视频 | 99久久精品免费看 |