1. AQS基本屬性
- CAS算法:
CAS, CPU指令,在大多數處理器架構,包括IA32、Space中採用的都是CAS指令,CAS的語義是“我認爲V的值應該爲A,如果是,那麼將V的值更新爲B,否則不修改並告訴V的值實際爲多少”,CAS是項樂觀鎖技術,當多個線程嘗試使用CAS同時更新同一個變量時,只有其中一個線程能更新變量的值,而其它線程都失敗,失敗的線程並不會被掛起,而是被告知這次競爭中失敗,並可以再次嘗試。CAS有3個操作數,內存值V,舊的預期值A,要修改的新值B。當且僅當預期值A和內存值V相同時,將內存值V修改爲B,否則什麼都不做。- 核心接口:
getState()
setState()
compareAndSetState()
isHeldExclusively():該線程是否正在獨佔資源。只有用到condition才需要去實現它。
tryAcquire(int):獨佔方式。嘗試獲取資源,成功則返回true,失敗則返回false。
tryRelease(int):獨佔方式。嘗試釋放資源,成功則返回true,失敗則返回false。
tryAcquireShared(int):共享方式。嘗試獲取資源。負數表示失敗;0表示成功,但沒有剩餘可用資源;正數表示成功,且有剩餘資源。
tryReleaseShared(int):共享方式。嘗試釋放資源,成功則返回true,失敗則返回false。
-
狀態位
private volatile int state;
獲得鎖標識,通過調用Unsafe.compareAndSwapInt()實現。 - 獲得鎖的線程
private transient Thread exclusiveOwnerThread;
2. ReentrantLock
1. 非公平鎖
-
lock()
- 首先嚐試把state由0置爲1,如果成功把當前線程標記爲exclusiveOwnerThread,如果失敗進入2
- 當前線程形成Node對象,然後鏈至鏈表結尾。嘗試獲得鎖,不成功阻塞(LockSupport.park(Thread),調用Unsafe.park())
- unlock()
找到鏈表的head,head是個空的Node,其next指向鏈表中第一個等待的線程,然後喚醒此線程(LockSupport.unpark(Thread),調用Unsafe.unpark())
默認情況下ReentrantLock爲非公平鎖,其原因有如下三條:
- 新的線程上來就嘗試獲得鎖,有可能會獲取成功,導致等待時間長的線程沒有先執行。
- 新線程在第一次嘗試獲得鎖失敗後,在進入鏈表之前又嘗試獲得鎖,有可能導致新線程提前執行。
- 線程被喚醒後嘗試獲得鎖,有可能失敗,導致被延遲執行。
2. 公平鎖
與非公平鎖最大的區別是當嘗試獲得鎖時會先判斷鏈表中是否有排隊的線程,如果沒有再嘗試獲得鎖,這樣可以保證按照鏈表的順序執行線程,保證了一種公平。