當(dāng)前位置:首頁 > 公眾號精選 > 小林coding
[導(dǎo)讀]直接進(jìn)入正題,發(fā)車!簡述java內(nèi)存模型(JMM)java內(nèi)存模型定義了程序中各種變量的訪問規(guī)則。其規(guī)定所有變量都存儲在主內(nèi)存,線程均有自己的工作內(nèi)存。工作內(nèi)存中保存被該線程使用的變量的主內(nèi)存副本,線程對變量的所有操作都必須在工作空間進(jìn)行,不能直接讀寫主內(nèi)存數(shù)據(jù)。操作完成后,線程...

直接進(jìn)入正題,發(fā)車!

簡述java內(nèi)存模型(JMM)

java內(nèi)存模型定義了程序中各種變量的訪問規(guī)則。其規(guī)定所有變量都存儲在主內(nèi)存,線程均有自己的工作內(nèi)存。工作內(nèi)存中保存被該線程使用的變量的主內(nèi)存副本,線程對變量的所有操作都必須在工作空間進(jìn)行,不能直接讀寫主內(nèi)存數(shù)據(jù)。操作完成后,線程的工作內(nèi)存通過緩存一致性協(xié)議將操作完的數(shù)據(jù)刷回主存。

簡述as-if-serial

編譯器等會對原始的程序進(jìn)行指令重排序和優(yōu)化。但不管怎么重排序,其結(jié)果和用戶原始程序輸出預(yù)定結(jié)果一致。

簡述happens-before八大原則

程序次序規(guī)則:一個線程內(nèi)寫在前面的操作先行發(fā)生于后面的。

鎖定規(guī)則:unlock 操作先行發(fā)生于后面對同一個鎖的 lock 操作。

volatile 規(guī)則:對 volatile 變量的寫操作先行發(fā)生于后面的讀操作。

線程啟動規(guī)則:線程的 start 方法先行發(fā)生于線程的每個動作。

線程中斷規(guī)則:對線程interrupt()方法的調(diào)用先行發(fā)生于被中斷線程的代碼檢測到中斷事件的發(fā)生。

線程終止規(guī)則:線程中所有操作先行發(fā)生于對線程的終止檢測。

對象終結(jié)規(guī)則:對象的初始化先行發(fā)生于 finalize 方法。

傳遞性規(guī)則:如果操作 A 先行發(fā)生于操作 B,操作 B 先行發(fā)生于操作 C,那么操作 A 先行發(fā)生于操作 C

as-if-serial 和 happens-before 的區(qū)別

as-if-serial 保證單線程程序的執(zhí)行結(jié)果不變,happens-before 保證正確同步的多線程程序的執(zhí)行結(jié)果不變。

簡述原子性操作

一個操作或者多個操作,要么全部執(zhí)行并且執(zhí)行的過程不會被任何因素打斷,要么就都不執(zhí)行,這就是原子性操作。

簡述線程的可見性

可見性指當(dāng)一個線程修改了共享變量時,其他線程能夠立即得知修改。volatile,synchronized,final都能保證可見性。

簡述有序性

即雖然多線程存在并發(fā)和指令優(yōu)化等操作,在本線程內(nèi)觀察該線程的所有執(zhí)行操作是有序的。

簡述java中volatile關(guān)鍵字作用

  1. 保證變量對所有線程的可見性。當(dāng)一條線程修改了變量值,新值對于其他線程來說是立即可以得知的。
  2. 禁止指令重排序優(yōu)化。使用 volatile 變量進(jìn)行寫操作,匯編指令帶有 lock 前綴,相當(dāng)于一個內(nèi)存屏障,編譯器不會將后面的指令重排到內(nèi)存屏障之前。

java線程的實現(xiàn)方式

  1. 實現(xiàn)Runnable接口
  2. 繼承Thread類。
  3. 實現(xiàn)Callable接口

簡述java線程的狀態(tài)

線程狀態(tài)有New, RUNNABLE, BLOCK, WAITING, TIMED_WAITING, THERMINATED NEW:新建狀態(tài),線程被創(chuàng)建且未啟動,此時還未調(diào)用 start 方法。

RUNNABLE: 運(yùn)行狀態(tài)。其表示線程正在JVM中執(zhí)行,但是這個執(zhí)行,不一定真的在跑,也可能在排隊等CPU。

BLOCKED:阻塞狀態(tài)。線程等待獲取鎖,鎖還沒獲得。

WAITING: 等待狀態(tài)。線程內(nèi)run方法運(yùn)行完語句Object.wait()/Thread.join()進(jìn)入該狀態(tài)。

TIMED_WAITING:限期等待。在一定時間之后跳出狀態(tài)。調(diào)用Thread.sleep(long) Object.wait(long) Thread.join(long)進(jìn)入狀態(tài)。其中這些參數(shù)代表等待的時間。

TERMINATED:結(jié)束狀態(tài)。線程調(diào)用完run方法進(jìn)入該狀態(tài)。

簡述線程通信的方式

  1. volatile 關(guān)鍵詞修飾變量,保證所有線程對變量訪問的可見性。
  2. synchronized關(guān)鍵詞。確保多個線程在同一時刻只能有一個處于方法或同步塊中。
  3. wait/notify方法
  4. IO通信

簡述線程池

沒有線程池的情況下,多次創(chuàng)建,銷毀線程開銷比較大。如果在開辟的線程執(zhí)行完當(dāng)前任務(wù)后執(zhí)行接下來任務(wù),復(fù)用已創(chuàng)建的線程,降低開銷、控制最大并發(fā)數(shù)。

線程池創(chuàng)建線程時,會將線程封裝成工作線程 Worker,Worker 在執(zhí)行完任務(wù)后還會循環(huán)獲取工作隊列中的任務(wù)來執(zhí)行。

將任務(wù)派發(fā)給線程池時,會出現(xiàn)以下幾種情況

  1. 核心線程池未滿,創(chuàng)建一個新的線程執(zhí)行任務(wù)。

  2. 如果核心線程池已滿,工作隊列未滿,將線程存儲在工作隊列。

  3. 如果工作隊列已滿,線程數(shù)小于最大線程數(shù)就創(chuàng)建一個新線程處理任務(wù)。

  4. 如果超過大小線程數(shù),按照拒絕策略來處理任務(wù)。

線程池參數(shù)

  1. corePoolSize:常駐核心線程數(shù)。超過該值后如果線程空閑會被銷毀。

  2. maximumPoolSize:線程池能夠容納同時執(zhí)行的線程最大數(shù)。

  3. keepAliveTime:線程空閑時間,線程空閑時間達(dá)到該值后會被銷毀,直到只剩下 corePoolSize 個線程為止,避免浪費(fèi)內(nèi)存資源。

  4. workQueue:工作隊列。

  5. threadFactory:線程工廠,用來生產(chǎn)一組相同任務(wù)的線程。

  6. handler:拒絕策略。有以下幾種拒絕策略:

  • AbortPolicy:丟棄任務(wù)并拋出異常
  • CallerRunsPolicy:重新嘗試提交該任務(wù)
  • DiscardOldestPolicy 拋棄隊列里等待最久的任務(wù)并把當(dāng)前任務(wù)加入隊列
  • DiscardPolicy 表示直接拋棄當(dāng)前任務(wù)但不拋出異常。

線程池創(chuàng)建方法

  1. newFixedThreadPool,創(chuàng)建固定大小的線程池。

  2. newSingleThreadExecutor,使用單線程線程池。

  3. newCachedThreadPool,maximumPoolSize 設(shè)置為 Integer 最大值,工作完成后會回收工作線程

  4. newScheduledThreadPool:支持定期及周期性任務(wù)執(zhí)行,不回收工作線程。

  5. newWorkStealingPool:一個擁有多個任務(wù)隊列的線程池。

簡述Executor框架

Executor框架目的是將任務(wù)提交和任務(wù)如何運(yùn)行分離開來的機(jī)制。用戶不再需要從代碼層考慮設(shè)計任務(wù)的提交運(yùn)行,只需要調(diào)用Executor框架實現(xiàn)類的Execute方法就可以提交任務(wù)。產(chǎn)生線程池的函數(shù)ThreadPoolExecutor也是Executor的具體實現(xiàn)類。

簡述Executor的繼承關(guān)系

  • Executor:一個接口,其定義了一個接收Runnable對象的方法executor,該方法接收一個Runable實例執(zhí)行這個任務(wù)。
  • ExecutorService:Executor的子類接口,其定義了一個接收Callable對象的方法,返回 Future 對象,同時提供execute方法。
  • ScheduledExecutorService:ExecutorService的子類接口,支持定期執(zhí)行任務(wù)。
  • AbstractExecutorService:抽象類,提供 ExecutorService 執(zhí)行方法的默認(rèn)實現(xiàn)。
  • Executors:實現(xiàn)ExecutorService接口的靜態(tài)工廠類,提供了一系列工廠方法用于創(chuàng)建線程池。
  • ThreadPoolExecutor:繼承AbstractExecutorService,用于創(chuàng)建線程池。
  • ForkJoinPool: 繼承AbstractExecutorService,F(xiàn)ork 將大任務(wù)分叉為多個小任務(wù),然后讓小任務(wù)執(zhí)行,Join 是獲得小任務(wù)的結(jié)果,類似于map reduce。
  • ThreadPoolExecutor:繼承ThreadPoolExecutor,實現(xiàn)ScheduledExecutorService,用于創(chuàng)建帶定時任務(wù)的線程池。

簡述線程池的狀態(tài)

  • Running:能接受新提交的任務(wù),也可以處理阻塞隊列的任務(wù)。
  • Shutdown:不再接受新提交的任務(wù),但可以處理存量任務(wù),線程池處于running時調(diào)用shutdown方法,會進(jìn)入該狀態(tài)。
  • Stop:不接受新任務(wù),不處理存量任務(wù),調(diào)用shutdownnow進(jìn)入該狀態(tài)。
  • Tidying:所有任務(wù)已經(jīng)終止了,worker_count(有效線程數(shù))為0。
  • Terminated:線程池徹底終止。在tidying模式下調(diào)用terminated方法會進(jìn)入該狀態(tài)。

簡述阻塞隊列

阻塞隊列是生產(chǎn)者消費(fèi)者的實現(xiàn)具體組件之一。當(dāng)阻塞隊列為空時,從隊列中獲取元素的操作將會被阻塞,當(dāng)阻塞隊列滿了,往隊列添加元素的操作將會被阻塞。具體實現(xiàn)有:

  • ArrayBlockingQueue:底層是由數(shù)組組成的有界阻塞隊列。
  • LinkedBlockingQueue:底層是由鏈表組成的有界阻塞隊列。
  • PriorityBlockingQueue:阻塞優(yōu)先隊列。
  • DelayQueue:創(chuàng)建元素時可以指定多久才能從隊列中獲取當(dāng)前元素
  • SynchronousQueue:不存儲元素的阻塞隊列,每一個存儲必須等待一個取出操作
  • LinkedTransferQueue:與LinkedBlockingQueue相比多一個transfer方法,即如果當(dāng)前有消費(fèi)者正等待接收元素,可以把生產(chǎn)者傳入的元素立刻傳輸給消費(fèi)者。
  • LinkedBlockingDeque:雙向阻塞隊列。

談一談ThreadLocal

ThreadLocal 是線程共享變量。ThreadLoacl 有一個靜態(tài)內(nèi)部類 ThreadLocalMap,其 Key 是 ThreadLocal 對象,值是 Entry 對象,ThreadLocalMap是每個線程私有的。

  • set 給ThreadLocalMap設(shè)置值。
  • get 獲取ThreadLocalMap。
  • remove 刪除ThreadLocalMap類型的對象。
存在的問題

  1. 對于線程池,由于線程池會重用 Thread 對象,因此與 Thread 綁定的 ThreadLocal 也會被重用,造成一系列問題。

  2. 內(nèi)存泄漏。由于 ThreadLocal 是弱引用,但 Entry 的 value 是強(qiáng)引用,因此當(dāng) ThreadLocal 被垃圾回收后,value 依舊不會被釋放,產(chǎn)生內(nèi)存泄漏。

聊聊你對java并發(fā)包下unsafe類的理解

對于 Java 語言,沒有直接的指針組件,一般也不能使用偏移量對某塊內(nèi)存進(jìn)行操作。這些操作相對來講是安全(safe)的。

Java 有個類叫 Unsafe 類,這個類類使 Java 擁有了像 C 語言的指針一樣操作內(nèi)存空間的能力,同時也帶來了指針的問題。這個類可以說是 Java 并發(fā)開發(fā)的基礎(chǔ)。

JAVA中的樂觀鎖與CAS算法

對于樂觀鎖,開發(fā)者認(rèn)為數(shù)據(jù)發(fā)送時發(fā)生并發(fā)沖突的概率不大,所以讀操作前不上鎖。

到了寫操作時才會進(jìn)行判斷,數(shù)據(jù)在此期間是否被其他線程修改。如果發(fā)生修改,那就返回寫入失敗;如果沒有被修改,那就執(zhí)行修改操作,返回修改成功。

樂觀鎖一般都采用 Compare And Swap(CAS)算法進(jìn)行實現(xiàn)。顧名思義,該算法涉及到了兩個操作,比較(Compare)和交換(Swap)。

CAS 算法的思路如下:

  1. 該算法認(rèn)為不同線程對變量的操作時產(chǎn)生競爭的情況比較少。
  2. 該算法的核心是對當(dāng)前讀取變量值 E 和內(nèi)存中的變量舊值 V 進(jìn)行比較。
  3. 如果相等,就代表其他線程沒有對該變量進(jìn)行修改,就將變量值更新為新值 N。
  4. 如果不等,就認(rèn)為在讀取值 E 到比較階段,有其他線程對變量進(jìn)行過修改,不進(jìn)行任何操作。

ABA問題及解決方法簡述

CAS 算法是基于值來做比較的,如果當(dāng)前有兩個線程,一個線程將變量值從 A 改為 B ,再由 B 改回為 A ,當(dāng)前線程開始執(zhí)行 CAS 算法時,就很容易認(rèn)為值沒有變化,誤認(rèn)為讀取數(shù)據(jù)到執(zhí)行 CAS 算法的期間,沒有線程修改過數(shù)據(jù)。

juc 包提供了一個 AtomicStampedReference,即在原始的版本下加入版本號戳,解決 ABA 問題。

簡述常見的Atomic類

在很多時候,我們需要的僅僅是一個簡單的、高效的、線程安全的 或者--方案,使用synchronized關(guān)鍵字和lock固然可以實現(xiàn),但代價比較大,此時用原子類更加方便?;緮?shù)據(jù)類型的原子類有:

  • AtomicInteger 原子更新整形
  • AtomicLong 原子更新長整型
  • AtomicBoolean 原子更新布爾類型
Atomic數(shù)組類型有:

  • AtomicIntegerArray 原子更新整形數(shù)組里的元素
  • AtomicLongArray 原子更新長整型數(shù)組里的元素
  • AtomicReferenceArray 原子更新引用類型數(shù)組里的元素。
Atomic引用類型有

  • AtomicReference 原子更新引用類型
  • AtomicMarkableReference 原子更新帶有標(biāo)記位的引用類型,可以綁定一個 boolean 標(biāo)記
  • AtomicStampedReference 原子更新帶有版本號的引用類型
FieldUpdater類型:

  • AtomicIntegerFieldUpdater 原子更新整形字段的更新器
  • AtomicLongFieldUpdater 原子更新長整形字段的更新器
  • AtomicReferenceFieldUpdater 原子更新引用類型字段的更新器

簡述Atomic類基本實現(xiàn)原理

以AtomicIntger 為例:方法getAndIncrement:以原子方式將當(dāng)前的值加1,具體實現(xiàn)為:

  1. 在 for 死循環(huán)中取得 AtomicInteger 里存儲的數(shù)值
  2. 對 AtomicInteger 當(dāng)前的值加 1
  3. 調(diào)用 compareAndSet 方法進(jìn)行原子更新
  4. 先檢查當(dāng)前數(shù)值是否等于 expect
  5. 如果等于則說明當(dāng)前值沒有被其他線程修改,則將值更新為 next,
  6. 如果不是會更新失敗返回 false,程序會進(jìn)入 for 循環(huán)重新進(jìn)行 compareAndSet 操作。

簡述CountDownLatch

countDownLatch這個類使一個線程等待其他線程各自執(zhí)行完畢后再執(zhí)行。是通過一個計數(shù)器來實現(xiàn)的,計數(shù)器的初始值是線程的數(shù)量。每當(dāng)一個線程執(zhí)行完畢后,調(diào)用countDown方法,計數(shù)器的值就減1,當(dāng)計數(shù)器的值為0時,表示所有線程都執(zhí)行完畢,然后在等待的線程就可以恢復(fù)工作了。只能一次性使用,不能reset。

簡述CyclicBarrier

CyclicBarrier 主要功能和countDownLatch類似,也是通過一個計數(shù)器,使一個線程等待其他線程各自執(zhí)行完畢后再執(zhí)行。但是其可以重復(fù)使用(reset)。

簡述Semaphore

Semaphore即信號量。Semaphore 的構(gòu)造方法參數(shù)接收一個 int 值,設(shè)置一個計數(shù)器,表示可用的許可數(shù)量即最大并發(fā)數(shù)。使用 acquire 方法獲得一個許可證,計數(shù)器減一,使用 release 方法歸還許可,計數(shù)器加一。如果此時計數(shù)器值為0,線程進(jìn)入休眠。

簡述Exchanger

Exchanger類可用于兩個線程之間交換信息??珊唵蔚貙xchanger對象理解為一個包含兩個格子的容器,通過exchanger方法可以向兩個格子中填充信息。線程通過exchange 方法交換數(shù)據(jù),第一個線程執(zhí)行 exchange 方法后會阻塞等待第二個線程執(zhí)行該方法。當(dāng)兩個線程都到達(dá)同步點(diǎn)時這兩個線程就可以交換數(shù)據(jù)當(dāng)兩個格子中的均被填充時,該對象會自動將兩個格子的信息交換,然后返回給線程,從而實現(xiàn)兩個線程的信息交換。

簡述ConcurrentHashMap

JDK7采用鎖分段技術(shù)。首先將數(shù)據(jù)分成 Segment 數(shù)據(jù)段,然后給每一個數(shù)據(jù)段配一把鎖,當(dāng)一個線程占用鎖訪問其中一個段的數(shù)據(jù)時,其他段的數(shù)據(jù)也能被其他線程訪問。

get 除讀到空值不需要加鎖。該方法先經(jīng)過一次再散列,再用這個散列值通過散列運(yùn)算定位到 Segment,最后通過散列算法定位到元素。put 須加鎖,首先定位到 Segment,然后進(jìn)行插入操作,第一步判斷是否需要對 Segment 里的 HashEntry 數(shù)組進(jìn)行擴(kuò)容,第二步定位添加元素的位置,然后將其放入數(shù)組。

JDK8的改進(jìn)

  1. 取消分段鎖機(jī)制,采用CAS算法進(jìn)行值的設(shè)置,如果CAS失敗再使用 synchronized 加鎖添加元素
  2. 引入紅黑樹結(jié)構(gòu),當(dāng)某個槽內(nèi)的元素個數(shù)超過8且 Node數(shù)組 容量大于 64 時,鏈表轉(zhuǎn)為紅黑樹。
  3. 使用了更加優(yōu)化的方式統(tǒng)計集合內(nèi)的元素數(shù)量。

Synchronized底層實現(xiàn)原理

Java 對象底層都關(guān)聯(lián)一個的 monitor,使用 synchronized 時 JVM 會根據(jù)使用環(huán)境找到對象的 monitor,根據(jù) monitor 的狀態(tài)進(jìn)行加解鎖的判斷。如果成功加鎖就成為該 monitor 的唯一持有者,monitor 在被釋放前不能再被其他線程獲取。

synchronized在JVM編譯后會產(chǎn)生monitorenter 和 monitorexit 這兩個字節(jié)碼指令,獲取和釋放 monitor。這兩個字節(jié)碼指令都需要一個引用類型的參數(shù)指明要鎖定和解鎖的對象,對于同步普通方法,鎖是當(dāng)前實例對象;對于靜態(tài)同步方法,鎖是當(dāng)前類的 Class 對象;對于同步方法塊,鎖是 synchronized 括號里的對象。

執(zhí)行 monitorenter 指令時,首先嘗試獲取對象鎖。如果這個對象沒有被鎖定,或當(dāng)前線程已經(jīng)持有鎖,就把鎖的計數(shù)器加 1,執(zhí)行 monitorexit 指令時會將鎖計數(shù)器減 1。一旦計數(shù)器為 0 鎖隨即就被釋放。

Synchronized關(guān)鍵詞使用方法

  1. 直接修飾某個實例方法
  2. 直接修飾某個靜態(tài)方法
  3. 修飾代碼塊

簡述java偏向鎖

JDK 1.6 中提出了偏向鎖的概念。該鎖提出的原因是,開發(fā)者發(fā)現(xiàn)多數(shù)情況下鎖并不存在競爭,一把鎖往往是由同一個線程獲得的。偏向鎖并不會主動釋放,這樣每次偏向鎖進(jìn)入的時候都會判斷該資源是否是偏向自己的,如果是偏向自己的則不需要進(jìn)行額外的操作,直接可以進(jìn)入同步操作。

其申請流程為:

  1. 首先需要判斷對象的 Mark Word 是否屬于偏向模式,如果不屬于,那就進(jìn)入輕量級鎖判斷邏輯。否則繼續(xù)下一步判斷;
  2. 判斷目前請求鎖的線程 ID 是否和偏向鎖本身記錄的線程 ID 一致。如果一致,繼續(xù)下一步的判斷,如果不一致,跳轉(zhuǎn)到步驟4;
  3. 判斷是否需要重偏向。如果不用的話,直接獲得偏向鎖;
  4. 利用 CAS 算法將對象的 Mark Word 進(jìn)行更改,使線程 ID 部分換成本線程 ID。如果更換成功,則重偏向完成,獲得偏向鎖。如果失敗,則說明有多線程競爭,升級為輕量級鎖。

簡述輕量級鎖

輕量級鎖是為了在沒有競爭的前提下減少重量級鎖出現(xiàn)并導(dǎo)致的性能消耗。

其申請流程為:

  1. 如果同步對象沒有被鎖定,虛擬機(jī)將在當(dāng)前線程的棧幀中建立一個鎖記錄空間,存儲鎖對象目前 Mark Word 的拷貝。
  2. 虛擬機(jī)使用 CAS 嘗試把對象的 Mark Word 更新為指向鎖記錄的指針
  3. 如果更新成功即代表該線程擁有了鎖,鎖標(biāo)志位將轉(zhuǎn)變?yōu)?00,表示處于輕量級鎖定狀態(tài)。
  4. 如果更新失敗就意味著至少存在一條線程與當(dāng)前線程競爭。虛擬機(jī)檢查對象的 Mark Word 是否指向當(dāng)前線程的棧幀
  5. 如果指向當(dāng)前線程的棧幀,說明當(dāng)前線程已經(jīng)擁有了鎖,直接進(jìn)入同步塊繼續(xù)執(zhí)行
  6. 如果不是則說明鎖對象已經(jīng)被其他線程搶占。
  7. 如果出現(xiàn)兩條以上線程爭用同一個鎖,輕量級鎖就不再有效,將膨脹為重量級鎖,鎖標(biāo)志狀態(tài)變?yōu)?10,此時Mark Word 存儲的就是指向重量級鎖的指針,后面等待鎖的線程也必須阻塞。

簡述鎖優(yōu)化策略

即自適應(yīng)自旋、鎖消除、鎖粗化、鎖升級等策略偏。

簡述java的自旋鎖

線程獲取鎖失敗后,可以采用這樣的策略,可以不放棄 CPU ,不停的重試內(nèi)重試,這種操作也稱為自旋鎖。

簡述自適應(yīng)自旋鎖

自適應(yīng)自旋鎖自旋次數(shù)不再人為設(shè)定,通常由前一次在同一個鎖上的自旋時間及鎖的擁有者的狀態(tài)決定。

簡述鎖粗化

鎖粗化的思想就是擴(kuò)大加鎖范圍,避免反復(fù)的加鎖和解鎖。

簡述鎖消除

鎖消除是一種更為徹底的優(yōu)化,在編譯時,java編譯器對運(yùn)行上下文進(jìn)行掃描,去除不可能存在共享資源競爭的鎖。

簡述Lock與ReentrantLock

Lock 接是 java并發(fā)包的頂層接口。

可重入鎖 ReentrantLock 是 Lock 最常見的實現(xiàn),與 synchronized 一樣可重入。ReentrantLock 在默認(rèn)情況下是非公平的,可以通過構(gòu)造方法指定公平鎖。一旦使用了公平鎖,性能會下降。

簡述AQS

AQS(AbstractQuenedSynchronizer)抽象的隊列式同步器。AQS是將每一條請求共享資源的線程封裝成一個鎖隊列的一個結(jié)點(diǎn)(Node),來實現(xiàn)鎖的分配。AQS是用來構(gòu)建鎖或其他同步組件的基礎(chǔ)框架,它使用一個 volatile int state 變量作為共享資源,如果線程獲取資源失敗,則進(jìn)入同步隊列等待;如果獲取成功就執(zhí)行臨界區(qū)代碼,釋放資源時會通知同步隊列中的等待線程。

子類通過繼承同步器并實現(xiàn)它的抽象方法getState、setState 和 compareAndSetState對同步狀態(tài)進(jìn)行更改。

AQS獲取獨(dú)占鎖/釋放獨(dú)占鎖原理

獲?。海╝cquire)

  1. 調(diào)用 tryAcquire 方法安全地獲取線程同步狀態(tài),獲取失敗的線程會被構(gòu)造同步節(jié)點(diǎn)并通過 addWaiter 方法加入到同步隊列的尾部,在隊列中自旋。
  2. 調(diào)用 acquireQueued 方法使得該節(jié)點(diǎn)以死循環(huán)的方式獲取同步狀態(tài),如果獲取不到則阻塞。
釋放:(release)

  1. 調(diào)用 tryRelease 方法釋放同步狀態(tài)
  2. 調(diào)用 unparkSuccessor 方法喚醒頭節(jié)點(diǎn)的后繼節(jié)點(diǎn),使后繼節(jié)點(diǎn)重新嘗試獲取同步狀態(tài)。

AQS獲取共享鎖/釋放共享鎖原理

獲取鎖(acquireShared)

  1. 調(diào)用 tryAcquireShared 方法嘗試獲取同步狀態(tài),返回值不小于 0 表示能獲取同步狀態(tài)。
釋放(releaseShared)

  1. 釋放,并喚醒后續(xù)處于等待狀態(tài)的節(jié)點(diǎn)。

線程池類型

  1. newCachedThreadPool 可緩存線程池,可設(shè)置最小線程數(shù)和最大線程數(shù),線程空閑1分鐘后自動銷毀。
  2. newFixedThreadPool 指定工作線程數(shù)量線程池。
  3. newSingleThreadExecutor 單線程Executor。
  4. newScheduleThreadPool 支持定時任務(wù)的指定工作線程數(shù)量線程池。
  5. newSingleThreadScheduledExecutor 支持定時任務(wù)的單線程Executor。

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉(zhuǎn)型技術(shù)解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關(guān)鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風(fēng)險,如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競爭力 堅持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競爭優(yōu)勢...

關(guān)鍵字: 通信 BSP 電信運(yùn)營商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術(shù)學(xué)會聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(shù)(集團(tuán))股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉