網上關於 Java 中鎖的內容有不少,因此我寫的這些內容百度都不怎麼喜歡,也很難搜索這些知識點到個人我的網站上。可是這些內容呢?我是想選擇性的發表的個人我的微信公衆號裏!下面咱們開始本章的內容吧!微信
公平鎖是指多個線程按照申請鎖的順序來獲取鎖,線程直接進入隊列中排隊,隊列中的第一個線程才能得到鎖。公平鎖的優勢是等待鎖的線程不會餓死。缺點是總體吞吐效率相對非公平鎖要低,等待隊列中除第一個線程之外的全部線程都會阻塞,CPU 喚醒阻塞線程的開銷比非公平鎖大。flex
非公平鎖是多個線程加鎖時直接嘗試獲取鎖,獲取不到纔會到等待隊列的隊尾等待。但若是此時鎖恰好可用,那麼這個線程能夠無需阻塞直接獲取到鎖,因此非公平鎖有可能出現後申請鎖的線程先獲取鎖的場景。非公平鎖的優勢是能夠減小喚起線程的開銷,總體的吞吐效率高,由於線程有概率不阻塞直接得到鎖,CPU 沒必要喚醒全部線程。缺點是處於等待隊列中的線程可能會餓死,或者等好久纔會得到鎖。網站
上面的解釋可能優勢抽象,下面咱們經過一張圖來區別什麼是公平鎖?什麼是非公平鎖?spa
如上圖所示,假設有一口水井,有管理員看守,管理員有一把鎖,只有拿到鎖的人才可以打水,打完水要把鎖還給管理員。每一個過來打水的人都要管理員的容許並拿到鎖以後才能去打水,若是前面有人正在打水,那麼這個想要打水的人就必須排隊。管理員會查看下一個要去打水的人是否是隊伍裏排最前面的人,若是是的話,纔會給你鎖讓你去打水;若是你不是排第一的人,就必須去隊尾排隊,這就是公平鎖。.net
可是對於非公平鎖,管理員對打水的人沒有要求。即便等待隊伍裏有排隊等待的人,但若是在上一我的剛打完水把鎖還給管理員並且管理員尚未容許等待隊伍裏下一我的去打水時,恰好來了一個插隊的人,這個插隊的人是能夠直接從管理員那裏拿到鎖去打水,不須要排隊,本來排隊等待的人只能繼續等待。以下圖所示(仍是打水的例子):線程
完全的理解了 Java 中的公平鎖與非公平鎖後,咱們來看看 Java 中的 ReentrantLock。3d
閱讀過 ReentrantLock 源碼的都知道,它裏面有一個內部類 Sync,Sync 繼承 AQS(AbstractQueuedSynchronizer),添加鎖和釋放鎖的大部分操做實際上都是在 Sync 中實現的。它有公平鎖 FairSync 和非公平鎖 NonfairSync 兩個子類。ReentrantLock 默認使用非公平鎖,也能夠經過構造器來顯示的指定使用公平鎖。blog
下面咱們來看一下公平鎖與非公平鎖的加鎖方法的源碼:繼承
經過上圖中的源代碼對比,咱們能夠明顯的看出公平鎖與非公平鎖的 lock() 方法惟一的區別就在於公平鎖在獲取同步狀態時多了一個限制條件:hasQueuedPredecessors()。
再進入 hasQueuedPredecessors(),能夠看到該方法主要作一件事情:主要是判斷當前線程是否位於同步隊列中的第一個。若是是則返回 true,不然返回 false。
綜上,公平鎖就是經過同步隊列來實現多個線程按照申請鎖的順序來獲取鎖,從而實現公平的特性。非公平鎖加鎖時不考慮排隊等待問題,直接嘗試獲取鎖,因此存在後申請卻先得到鎖的狀況。
Java 中使用公平鎖的場景就是隊列,FIFO。使用非公平鎖的場景就是 ReentrantLock(默認非公平鎖)!
最後,歡迎關注個人我的微信公衆號:業餘草(yyucao)!可加QQ1羣:135430763(2000人羣已滿),QQ2羣:454796847,QQ3羣:187424846。QQ羣進羣密碼:xttblog,想加微信羣的朋友,能夠微信搜索:xmtxtt,備註:「xttblog」,添加助理微信拉你進羣。備註錯誤不會贊成好友申請。再次感謝您的關注!後續有精彩內容會第一時間發給您!原創文章投稿請發送至532009913@qq.com郵箱。商務合做可添加助理微信進行溝通!