CAS(Compare and Set)
無鎖演算法,不使用鎖的情況下實作多執行緒之間的變數同步,拿變數的原值和記憶體中的值進行比較,如果相同,則原值沒有被修改過,那么就將原值修改為新值,失敗的執行緒不會掛起,繼續回圈;
Java 中的 AtomicInteger 類就用了CAS操作,
AtomicInteger atomicInteger = new AtomicInteger(1); //先對比,后設定,如果等于1,更新值為2 Boolean b =atomicInteger.compareAndSet(1, 2);
比起鎖來性能提升了許多,但是因為頻繁回圈,會照成系統開銷增大,
ABA問題:如果值一開始是A,后來被改成了B又被改回了A,CAS會認為該變數沒被修改過,不過 Java 也提供了帶時間戳的類來解決這個問題,
AQS(AbstractQueuedSynchronizer)
抽象佇列同步器,支持 獨占(exclusive ) 與 共享(shared) 兩種模式,維護一個整形的 volatile 變數 state 和佇列來實作同步,通過 CAS 來更新state值(執行緒個數一致),AQS 也支持自定義同步器同時實作獨占和共享兩種方式,如ReentrantReadWriteLock;
直接嘗試占有,先判斷state是否為0(可獲取),然后將0累計加1,當前執行緒設定為鎖持有(lock())執行緒,并回傳成功;如果失敗則依次排隊,釋放鎖(unlock())state-1;
java很多同步框架都依賴于AQS,比如 CountDownLatch,ReentrantLock,Semaphore,
同步器基于模板方法模式,需要自定義模版繼承 AbstractQueuedSynchronizer ,重寫方法(state 的獲取和釋放),Semaphore(信號量)可以指定多個執行緒同時訪問某個資源,
Semaphore
基于 AQS 實作,指定執行緒數量,當執行任務的執行緒數超出,多余的執行緒將會被放入阻塞佇列,
CountDownLatch
基于 AQS 實作,是一次性的,計數器的值只能在構造方法中初始化一次,
CyclicBarrier
指定執行緒數量,執行緒到達一個屏障會被阻塞(變數標識計數),直到指定的最后一個執行緒也到達屏障時,屏障才會打開,然后執行緒繼續運行,還可以指定到達屏障時,優先執行某些代碼塊,
ReentrantLock(公平鎖/非公平鎖)
依賴于AQS同步框架實作,可以指定建構式的boolean型別來得到公平鎖或非公平鎖,
公平鎖:先進先出,多個執行緒按照佇列的規則依次排隊,
非公平鎖:多個執行緒去獲取鎖的時候,會直接去嘗試獲取,獲取不到,再去進入等待佇列,
對比公平鎖更有機會搶占鎖,性能高于公平鎖,因為執行緒運行之間存在著延遲,非公平鎖能更充分的利用時間碎片,
synchronized(同步鎖)
作業系統的 mutex lock(互斥鎖)實作,表示只能有一個執行緒訪問該物件,ReentrantLock 功能更豐富,性能相等,
靜態方法類需要注意,如果new不同物件呼叫同一個靜態鎖方法,此時物件間會共用一把鎖,使該執行緒下方法里的代碼塊同步進行,
可重入鎖/不可重入鎖
可重入鎖:當執行緒獲取某個鎖后,還可以繼續獲取它,可以遞回呼叫,而不會發生死鎖,ReentrantLock 跟 synchronized 都是可重入鎖,
不可重入鎖:與可重入相反,獲取鎖后不能重復獲取,否則會自己鎖死自己,
獨享鎖/共享鎖
獨享鎖:該鎖每一次只能被一個執行緒所持有,比如 synchronized,
共享鎖:該鎖可被多個執行緒共有,
互斥鎖/讀寫鎖
互斥鎖:mutex lock,如果資源已經被加鎖,其它執行緒進入阻塞,直到當前行程解鎖,synchronized 為互斥鎖,
讀寫鎖:讀寫鎖既是互斥鎖,又是共享鎖,讀模式是共享,寫是互斥,讀讀不互斥,讀寫互斥,寫寫互斥,
樂觀鎖/悲觀鎖
樂觀鎖:假設都是無鎖狀態,
悲觀鎖:假設都是上鎖狀態,
分段鎖
是一種鎖的設計,并不是具體的一種鎖,ConcurrentHashMap 前期就是通過分段鎖來實作高效的并發操作,
每一把鎖都用于資料段,當多執行緒訪問不同資料段的資料時,從而降低鎖競爭,提高并發訪問效率,
自旋鎖
執行緒在鎖被占用時(不是阻塞),會不斷回圈去嘗試,直到獲取鎖,使得執行緒會保持活躍,減少了執行緒切換的開銷,但加重了等待時間,它是為實作保護共享資源而提出一種鎖機制,
偏向鎖/輕量級鎖/重量級鎖
不屬于java鎖,而是 Jvm 為了提高鎖的獲取與釋放效率而做的優化,
偏向鎖:某執行緒一直訪問 synchronized 鎖代碼,那么該執行緒會自動獲取鎖,降低獲取鎖的代價,
輕量級鎖:在偏向鎖的基礎上,另一個執行緒加入訪問,偏向鎖會自動升級為輕量級鎖,其他執行緒就可以通過自旋的形式嘗試獲取鎖而不被阻塞,以此提高性能,
重量級鎖:在輕量級鎖的基礎上,另一個執行緒加入訪問,處于自旋,當自旋一定次數還沒有獲取到鎖,就會進入阻塞,該鎖變為重量級鎖,重量級鎖會讓其他申請的執行緒進入阻塞,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/440481.html
標籤:Java
上一篇:Spring5原始碼決議-IOC之Scope作用域 一文讓你了解bean的作用域scope的底層實作
下一篇:六、Java方法
