您好,登錄后才能下訂單哦!
本篇文章為大家展示了Java 中怎么實(shí)現(xiàn)公平鎖與非公平鎖,內(nèi)容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細(xì)介紹希望你能有所收獲。
公平鎖是指多個(gè)線程按照申請鎖的順序來獲取鎖,線程直接進(jìn)入隊(duì)列中排隊(duì),隊(duì)列中的第一個(gè)線程才能獲得鎖。公平鎖的優(yōu)點(diǎn)是等待鎖的線程不會(huì)餓死。缺點(diǎn)是整體吞吐效率相對非公平鎖要低,等待隊(duì)列中除第一個(gè)線程以外的所有線程都會(huì)阻塞,CPU 喚醒阻塞線程的開銷比非公平鎖大。
非公平鎖是多個(gè)線程加鎖時(shí)直接嘗試獲取鎖,獲取不到才會(huì)到等待隊(duì)列的隊(duì)尾等待。但如果此時(shí)鎖剛好可用,那么這個(gè)線程可以無需阻塞直接獲取到鎖,所以非公平鎖有可能出現(xiàn)后申請鎖的線程先獲取鎖的場景。非公平鎖的優(yōu)點(diǎn)是可以減少喚起線程的開銷,整體的吞吐效率高,因?yàn)榫€程有幾率不阻塞直接獲得鎖,CPU 不必喚醒所有線程。缺點(diǎn)是處于等待隊(duì)列中的線程可能會(huì)餓死,或者等很久才會(huì)獲得鎖。
上面的解釋可能優(yōu)點(diǎn)抽象,下面我們通過一張圖來區(qū)別什么是公平鎖?什么是非公平鎖?
如上圖所示,假設(shè)有一口水井,有管理員看守,管理員有一把鎖,只有拿到鎖的人才能夠打水,打完水要把鎖還給管理員。每個(gè)過來打水的人都要管理員的允許并拿到鎖之后才能去打水,如果前面有人正在打水,那么這個(gè)想要打水的人就必須排隊(duì)。管理員會(huì)查看下一個(gè)要去打水的人是不是隊(duì)伍里排最前面的人,如果是的話,才會(huì)給你鎖讓你去打水;如果你不是排第一的人,就必須去隊(duì)尾排隊(duì),這就是公平鎖。
但是對于非公平鎖,管理員對打水的人沒有要求。即使等待隊(duì)伍里有排隊(duì)等待的人,但如果在上一個(gè)人剛打完水把鎖還給管理員而且管理員還沒有允許等待隊(duì)伍里下一個(gè)人去打水時(shí),剛好來了一個(gè)插隊(duì)的人,這個(gè)插隊(duì)的人是可以直接從管理員那里拿到鎖去打水,不需要排隊(duì),原本排隊(duì)等待的人只能繼續(xù)等待。如下圖所示(還是打水的例子):
徹底的理解了 Java 中的公平鎖與非公平鎖后,我們來看看 Java 中的 ReentrantLock。
閱讀過 ReentrantLock 源碼的都知道,它里面有一個(gè)內(nèi)部類 Sync,Sync 繼承 AQS(AbstractQueuedSynchronizer),添加鎖和釋放鎖的大部分操作實(shí)際上都是在 Sync 中實(shí)現(xiàn)的。它有公平鎖 FairSync 和非公平鎖 NonfairSync 兩個(gè)子類。ReentrantLock 默認(rèn)使用非公平鎖,也可以通過構(gòu)造器來顯示的指定使用公平鎖。
下面我們來看一下公平鎖與非公平鎖的加鎖方法的源碼:
通過上圖中的源代碼對比,我們可以明顯的看出公平鎖與非公平鎖的 lock() 方法唯一的區(qū)別就在于公平鎖在獲取同步狀態(tài)時(shí)多了一個(gè)限制條件:hasQueuedPredecessors()。
再進(jìn)入 hasQueuedPredecessors(),可以看到該方法主要做一件事情:主要是判斷當(dāng)前線程是否位于同步隊(duì)列中的第一個(gè)。如果是則返回 true,否則返回 false。
綜上,公平鎖就是通過同步隊(duì)列來實(shí)現(xiàn)多個(gè)線程按照申請鎖的順序來獲取鎖,從而實(shí)現(xiàn)公平的特性。非公平鎖加鎖時(shí)不考慮排隊(duì)等待問題,直接嘗試獲取鎖,所以存在后申請卻先獲得鎖的情況。
上述內(nèi)容就是Java 中怎么實(shí)現(xiàn)公平鎖與非公平鎖,你們學(xué)到知識或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識儲備,歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。