首頁技術(shù)文章正文

Java自旋鎖是什么?有什么優(yōu)缺點(diǎn)?

更新時(shí)間:2020-05-26 來源:黑馬程序員 瀏覽量:

1577370495235_學(xué)IT就到黑馬程序員.gif

自旋鎖原理非常簡(jiǎn)單,如果持有鎖的線程能在很短時(shí)間內(nèi)釋放鎖資源,那么那些等待競(jìng)爭(zhēng)鎖的線程就不需要做內(nèi)核態(tài)和用戶態(tài)之間的切換進(jìn)入阻塞掛起狀態(tài),它們只需要等一等(自旋),等持有鎖的線程釋放鎖后即可立即獲取鎖,這樣就避免用戶線程和內(nèi)核的切換的消耗。

線程自旋是需要消耗cup的,說白了就是讓cup在做無用功,如果一直獲取不到鎖,那線程也不能一直占用cup自旋做無用功,所以需要設(shè)定一個(gè)自旋等待的最大時(shí)間。

如果持有鎖的線程執(zhí)行的時(shí)間超過自旋等待的最大時(shí)間扔沒有釋放鎖,就會(huì)導(dǎo)致其它爭(zhēng)用鎖的線程在最大等待時(shí)間內(nèi)還是獲取不到鎖,這時(shí)爭(zhēng)用線程會(huì)停止自旋進(jìn)入阻塞狀態(tài)。

自旋鎖有什么優(yōu)缺點(diǎn)?

自旋鎖盡可能的減少線程的阻塞,這對(duì)于鎖的競(jìng)爭(zhēng)不激烈,且占用鎖時(shí)間非常短的代碼塊來說性能可以大幅度提升,因?yàn)樽孕南臅?huì)小于線程阻塞掛起再喚醒的操作的消耗,這些操作會(huì)導(dǎo)致線程發(fā)生兩次上下文切換!

但是如果鎖的競(jìng)爭(zhēng)激烈,或者持有鎖的線程需要長(zhǎng)時(shí)間占用鎖執(zhí)行同步塊,這時(shí)候就不適合使用自旋鎖了,因?yàn)樽孕i在獲取鎖前一直都是占用cpu做無用功,同時(shí)有大量線程在競(jìng)爭(zhēng)一個(gè)鎖,會(huì)導(dǎo)致獲取鎖的時(shí)間很長(zhǎng),線程自旋的消耗大于線程阻塞掛起操作的消耗,其它需要cup的線程又不能獲取到cpu,造成 cpu的浪費(fèi)。所以這種情況下我們要關(guān)閉自旋鎖;自旋鎖時(shí)間閾值(1.6 引入了適應(yīng)性自旋鎖)。

自旋鎖的目的是為了占著CPU的資源不釋放,等到獲取到鎖立即進(jìn)行處理。但是如何去選擇自旋的執(zhí)行時(shí)間呢?如果自旋執(zhí)行時(shí)間太長(zhǎng),會(huì)有大量的線程處于自旋狀態(tài)占用CPU資源,進(jìn)而會(huì)影響整體系統(tǒng)的性能。因此自旋的周期選的額外重要!

JVM 對(duì)于自旋周期的選擇,Jdk1.5這個(gè)限度是一定的寫死的,在1.6引入了適應(yīng)性自旋鎖,適應(yīng)性自旋鎖意味著自旋的時(shí)間不在是固定的了,而是由前一次在同一個(gè)鎖上的自旋時(shí)間以及鎖的擁有者的狀態(tài)來決定,基本認(rèn)為一個(gè)線程上下文切換的時(shí)間是最佳的一個(gè)時(shí)間,同時(shí)JVM還針對(duì)當(dāng)前CPU的負(fù)荷情況做了較多的優(yōu)化,如果平均負(fù)載小于CPUs則一直自旋,如果有超過(CPUs/2)個(gè)線程正在自旋,則后來線程直接阻塞,如果正在自旋的線程發(fā)現(xiàn)Owner發(fā)生了變化則延遲自旋時(shí)間(自旋計(jì)數(shù))或進(jìn)入阻塞,如果 CPU 處于節(jié)電模式則停止自旋,自旋時(shí)間的最壞情況是CPU的存儲(chǔ)延遲(CPU A 存儲(chǔ)了一個(gè)數(shù)據(jù),到CPU B得知這個(gè)數(shù)據(jù)直接的時(shí)間差),自旋時(shí)會(huì)適當(dāng)放棄線程優(yōu)先級(jí)之間的差異。

以上我們介紹了自旋鎖的原理和優(yōu)缺點(diǎn)希望對(duì)你有所幫助,如果您系統(tǒng)學(xué)習(xí)java提升java技術(shù)能力,推薦了解黑馬程序員java中級(jí)程序員培訓(xùn)課程。

在黑馬程序員學(xué)習(xí)java是什么體驗(yàn)?下面我們通過一個(gè)視頻來了解

1590050011625_咨詢課程小.jpg


猜你喜歡

Java面試:樂觀鎖和悲觀鎖分別是什么?

Java異常之throws關(guān)鍵字用法介紹

Java中sleep方法與wait方法的區(qū)別

分享到:
在線咨詢 我要報(bào)名
和我們?cè)诰€交談!