[TOC]
<br/>
> ### 隊列同步器
* 隊列同步器`AbstractQueuedSynchronizer`(以下簡稱同步器),是用來構建鎖或者其他同步組件的基礎框架,它使用了一個`int`成員變量表示同步狀態,通過內置的`FIFO`隊列來完成資源獲取線程的排隊工作.
* 鎖是面向使用者的,它定義了使用者與鎖交互的接口(比如可以允許兩個線程并行訪問),隱藏了實現細節;同步器面向的是鎖的實現者,它簡化了鎖的實現方式,屏蔽了同步狀態管理、線程的排隊、等待與喚醒等底層操作。鎖和同步器很好地隔離了使用者和實現者所需關注的領域。
* 同步器的設計是基于模板方法模式的,使用者需要繼承同步器并重寫指定的方法。
* `getState()`獲取當前同步狀態。
* `setState(int newState)`設置當前同步狀態。
* `compareAndSetState(int expect,int update)`使用CAS設置當前狀態,該方法能夠保證狀態設置的原子性
<br/>
> ### 隊列同步器的實現
* 同步器依賴內部的同步隊列(一個FIFO雙向隊列)來完成同步狀態的管理,當前線程獲取同步狀態失敗時,同步器會將當前線程以及等待狀態等信息構造成為一個節點(Node)并將其加入同步隊列,同時會阻塞當前線程,當同步狀態釋放時,會把首節點中的線程喚醒,使其再次嘗試獲取同步狀態。

* 節點進入同步隊列之后,就進入了一個自旋的過程,每個節點(或者說每個線程)都在自省地觀察,當條件滿足(自旋的判斷前驅節點是否為首節點并且能夠獲取到同步狀態,頭結點釋放同步狀態之后才會會喚醒后繼節點),就可以從這個自旋過程中退出,否則依舊留在這個自旋過程中(并會阻塞節點的線程)。

* 共享式獲取與獨占式獲取最主要的區別在于同一時刻能否有多個線程同時獲取到同步狀態。
* 在共享式獲取的自旋過程中,成功獲取到同步狀態并退出自旋的條件就是`tryAcquireShared(int arg)`方法返回值大于等于0。共享式獲取也需要釋放同步狀態,通過調用`releaseShared(int arg)`方法可以釋放同步狀態,對于能夠支持多個線程同時訪問的并發組件(比如Semaphore),它和獨占式主要區別在于`tryReleaseShared(int arg)`方法必須確保同步狀態(或者資源數)線程安全釋放,一般是通過循環和`CAS`來保證的,因為釋放同步狀態的操作會同時來自多個線程。
<br/>
> ### 公平鎖與非公平鎖的區別
* 公平性鎖每次都是從同步隊列中的第一個節點獲取到鎖,而非公平性鎖出現了一個線程連續獲取鎖的情況。
* 公平性鎖保證了鎖的獲取按照FIFO原則,而代價是進行大量的線程切換。非公平性鎖雖然可能造成線程“饑餓”,但極少的線程切換,保證了其更大的吞吐量。
<br/>
> ### `Condition`的實現分析
* 每個`Condition`對象都包含著一個隊列(以下稱為等待隊列),該隊列是`Condition`對象實現等待/通知功能的關鍵。
* 一個`Condition`包含一個等待隊列,`Condition`擁有首節點(firstWaiter)和尾節點(lastWaiter)。當前線程調用`Condition.await()`方法,將會以當前線程構造節點,并將節點從尾部加入等待隊列。`Condition`擁有首尾節點的引用,而新增節點只需要將原有的尾節點`nextWaiter`指向它,并且更新尾節點即可。上述節點引用更新的過程并沒有使用`CAS`保證,原因在于調用`await()`方法的線程必定是獲取了鎖的線程,也就是說該過程是由鎖來保證線程安全的。

* 在`Object`的監視器模型上,一個對象擁有一個同步隊列和等待隊列,而并發包中的`Lock`(更確切地說是同步器)擁有一個同步隊列和多個等待隊列。
* 等待,調用`Condition`的`await()`方法,會使當前線程進入等待隊列并釋放鎖,同時線程狀態變為等待狀態。如下圖:

* 通知,調用`Condition`的`signal()`方法,將會喚醒在等待隊列中等待時間最長的節點(首節點),在喚醒節點之前,會將節點移到同步隊列中。如下圖:

- asD
- Java
- Java基礎
- Java編譯器
- 反射
- collection
- IO
- JDK
- HashMap
- ConcurrentHashMap
- LinkedHashMap
- TreeMap
- 阻塞隊列
- java語法
- String.format()
- JVM
- JVM內存、對象、類
- JVM GC
- JVM監控
- 多線程
- 基礎概念
- volatile
- synchronized
- wait_notify
- join
- lock
- ThreadLocal
- AQS
- 線程池
- Spring
- IOC
- 特性介紹
- getBean()
- creatBean()
- createBeanInstance()
- populateBean()
- AOP
- 基本概念
- Spring處理請求的過程
- 注解
- 微服務
- 服務注冊與發現
- etcd
- zk
- 大數據
- Java_spark
- 基礎知識
- Thrift
- hdfs
- 計算機網絡
- OSI七層模型
- HTTP
- SSL
- 數據庫
- Redis
- mysql
- mybatis
- sql
- 容器
- docker
- k8s
- nginx
- tomcat
- 數據結構/算法
- 排序算法
- 快排
- 插入排序
- 歸并排序
- 堆排序
- 計算時間復雜度
- leetcode
- LRU緩存
- B/B+ 樹
- 跳躍表
- 設計模式
- 單例模式
- 裝飾者模式
- 工廠模式
- 運維
- git
- 前端
- thymeleaf
- 其他
- 代碼規范
- work_project
- Interview