在java的鎖機制中,公平和非公平的參考物是什么乍赫,個人而言覺得是相對產(chǎn)生的結果而立瓣蛀,簡單的來說,如果一個線程組里耿焊,能保證每個線程都能拿到鎖揪惦,那么這個鎖就是公平鎖。相反罗侯,如果保證不了每個線程都能拿到鎖器腋,也就是存在有線程餓死,那么這個鎖就是非公平鎖。本文圍繞ReenTrantLock來講纫塌。
小編推薦一個學JAVA的學習裙【四九二诊县,一七三,八四二】措左,無論你是牛還是小白依痊,是想轉行還是想入行都可以來了解一起進步一起學習!裙內有開發(fā)具怎披,很多干貨和技術資料分享實現(xiàn)原理
那如何能保證每個線程都能拿到鎖呢胸嘁,隊列FIFO是一個完美的解決方案,也就是先進先出凉逛,java的ReenTrantLock也就是用隊列實現(xiàn)的公平鎖和非公平鎖性宏。
在公平的鎖中,如果有另一個線程持有鎖或者有其他線程在等待隊列中等待這個所状飞,那么新發(fā)出的請求的線程將被放入到隊列中毫胜。而非公平鎖上,只有當鎖被某個線程持有時诬辈,新發(fā)出請求的線程才會被放入隊列中(此時和公平鎖是一樣的)酵使。所以,它們的差別在于非公平鎖會有更多的機會去搶占鎖焙糟。
公平鎖:
final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { if (!hasQueuedPredecessors() && compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } #hasQueuedPredecessors的實現(xiàn) public final boolean hasQueuedPredecessors() { Node t = tail; // Read fields in reverse initialization order Node h = head; Node s; return h != t && ((s = h.next) == null || s.thread != Thread.currentThread()); }
非公平鎖:
final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { if (compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } }
示例
小編推薦一個學JAVA的學習裙【四九二口渔,一七三,八四二】酬荞,無論你是牛還是小白搓劫,是想轉行還是想入行都可以來了解一起進步一起學習!裙內有開發(fā)具混巧,很多干貨和技術資料分享
公平鎖:
/** * Created by Fant.J. */public class MyFairLock { /** * true 表示 ReentrantLock 的公平鎖 */ private ReentrantLock lock = new ReentrantLock(true); public void testFail(){ try { lock.lock(); System.out.println(Thread.currentThread().getName() +"獲得了鎖"); }finally { lock.unlock(); } } public static void main(String[] args) { MyFairLock fairLock = new MyFairLock(); Runnable runnable = () -> { System.out.println(Thread.currentThread().getName()+"啟動"); nonfairLock.testFail(); }; Thread[] threadArray = new Thread[10]; for (int i=0; i<10; i++) { threadArray[i] = new Thread(runnable); } for (int i=0; i<10; i++) { threadArray[i].start(); } }}Thread-0啟動Thread-0獲得了鎖Thread-1啟動Thread-1獲得了鎖Thread-2啟動Thread-2獲得了鎖Thread-3啟動Thread-3獲得了鎖Thread-4啟動Thread-4獲得了鎖Thread-5啟動Thread-5獲得了鎖Thread-6啟動Thread-6獲得了鎖Thread-8啟動Thread-8獲得了鎖Thread-7啟動Thread-7獲得了鎖Thread-9啟動Thread-9獲得了鎖
可以看到枪向,獲取鎖的線程順序正是線程啟動的順序。
非公平鎖:
/** * Created by Fant.J. */public class MyNonfairLock { /** * false 表示 ReentrantLock 的非公平鎖 */ private ReentrantLock lock = new ReentrantLock(false); public void testFail(){ try { lock.lock(); System.out.println(Thread.currentThread().getName() +"獲得了鎖"); }finally { lock.unlock(); } } public static void main(String[] args) { MyNonfairLock nonfairLock = new MyNonfairLock(); Runnable runnable = () -> { System.out.println(Thread.currentThread().getName()+"啟動"); nonfairLock.testFail(); }; Thread[] threadArray = new Thread[10]; for (int i=0; i<10; i++) { threadArray[i] = new Thread(runnable); } for (int i=0; i<10; i++) { threadArray[i].start(); } }}Thread-1啟動Thread-0啟動Thread-0獲得了鎖Thread-1獲得了鎖Thread-8啟動Thread-8獲得了鎖Thread-3啟動Thread-3獲得了鎖Thread-4啟動Thread-4獲得了鎖Thread-5啟動Thread-2啟動Thread-9啟動Thread-5獲得了鎖Thread-2獲得了鎖Thread-9獲得了鎖Thread-6啟動Thread-7啟動Thread-6獲得了鎖Thread-7獲得了鎖
可以看出非公平鎖對鎖的獲取是亂序的咧党,即有一個搶占鎖的過程秘蛔。
最后
那非公平鎖和公平鎖適合什么場合使用呢,他們的優(yōu)缺點又是什么呢傍衡?
小編推薦一個學JAVA的學習裙【四九二深员,一七三,八四二】蛙埂,無論你是牛還是小白倦畅,是想轉行還是想入行都可以來了解一起進步一起學習!裙內有開發(fā)具绣的,很多干貨和技術資料分享
優(yōu)缺點:
非公平鎖性能高于公平鎖性能叠赐。首先欲账,在恢復一個被掛起的線程與該線程真正運行之間存在著嚴重的延遲。而且芭概,非公平鎖能更充分的利用cpu的時間片赛不,盡量的減少cpu空閑的狀態(tài)時間。
使用場景
使用場景的話呢罢洲,其實還是和他們的屬性一一相關踢故,舉個栗子:如果業(yè)務中線程占用(處理)時間要遠長于線程等待,那用非公平鎖其實效率并不明顯惹苗,但是用公平鎖會給業(yè)務增強很多的可控制性殿较。