一、synchronized鎖的基本原理
synchronized是Java中用于實(shí)現(xiàn)線(xiàn)程安全的關(guān)鍵字,它可以應(yīng)用于方法或代碼塊。當(dāng)一個(gè)線(xiàn)程進(jìn)入synchronized代碼塊時(shí),它將獲得一個(gè)鎖,其他線(xiàn)程在嘗試進(jìn)入同步代碼塊時(shí)會(huì)被阻塞,直到持有鎖的線(xiàn)程釋放鎖。
synchronized鎖的基本原理是基于對(duì)象的監(jiān)視器(monitor)。每個(gè)Java對(duì)象都有一個(gè)與之關(guān)聯(lián)的監(jiān)視器,這個(gè)監(jiān)視器可以被一個(gè)線(xiàn)程持有。當(dāng)一個(gè)線(xiàn)程獲取到對(duì)象的監(jiān)視器時(shí),它就可以執(zhí)行同步代碼塊,其他線(xiàn)程則需要等待。
二、synchronized鎖的升級(jí)
盡管synchronized鎖是簡(jiǎn)單易用的,但在高并發(fā)場(chǎng)景下性能可能不盡如人意。為了提高并發(fā)性能,Java引入了一些鎖的升級(jí)機(jī)制,具體如下:
1、偏向鎖(Biased Locking)
偏向鎖是JDK 6中引入的一種優(yōu)化機(jī)制。它的設(shè)計(jì)初衷是針對(duì)沒(méi)有競(jìng)爭(zhēng)的場(chǎng)景,假設(shè)在多數(shù)情況下,鎖總是由同一線(xiàn)程多次獲得的。在偏向鎖狀態(tài)下,當(dāng)一個(gè)線(xiàn)程獲取到鎖后,會(huì)在對(duì)象頭中記錄下自己的線(xiàn)程ID。這樣,下次該線(xiàn)程再次獲取鎖時(shí),無(wú)需進(jìn)行同步操作,可以直接進(jìn)入臨界區(qū)。
2、輕量級(jí)鎖(Lightweight Locking)
輕量級(jí)鎖是JDK 6中對(duì)synchronized鎖的升級(jí)改進(jìn)。它的目標(biāo)是在多個(gè)線(xiàn)程交替執(zhí)行同步塊的情況下,減少傳統(tǒng)的重量級(jí)鎖的開(kāi)銷(xiāo)。輕量級(jí)鎖的實(shí)現(xiàn)方式是通過(guò)CAS(Compare and Swap)操作來(lái)實(shí)現(xiàn),將對(duì)象頭中的一部分空間作為鎖記錄。當(dāng)多個(gè)線(xiàn)程競(jìng)爭(zhēng)同一鎖時(shí),會(huì)嘗試使用CAS操作來(lái)獲取鎖,成功則進(jìn)入臨界區(qū),失敗則升級(jí)為重量級(jí)鎖。
3、重量級(jí)鎖(Heavyweight Locking)
重量級(jí)鎖是synchronized鎖的默認(rèn)狀態(tài),也是最常見(jiàn)的狀態(tài)。當(dāng)多個(gè)線(xiàn)程競(jìng)爭(zhēng)同一鎖時(shí),會(huì)進(jìn)入重量級(jí)鎖狀態(tài)。在重量級(jí)鎖狀態(tài)下,競(jìng)爭(zhēng)失敗的線(xiàn)程會(huì)進(jìn)入阻塞狀態(tài),被放入鎖的等待隊(duì)列中。只有持有鎖的線(xiàn)程釋放鎖后,等待隊(duì)列中的線(xiàn)程才有機(jī)會(huì)獲取鎖進(jìn)入臨界區(qū)。
三、各個(gè)鎖的狀態(tài)對(duì)比
下面對(duì)偏向鎖、輕量級(jí)鎖和重量級(jí)鎖進(jìn)行簡(jiǎn)要對(duì)比,以便更好地理解它們之間的差異。
1、偏向鎖
適用場(chǎng)景:適用于多數(shù)情況下鎖總是由同一線(xiàn)程多次獲得的場(chǎng)景。獲取鎖的代價(jià):獲取偏向鎖的代價(jià)非常低,幾乎沒(méi)有額外開(kāi)銷(xiāo)。競(jìng)爭(zhēng)情況:當(dāng)其他線(xiàn)程嘗試競(jìng)爭(zhēng)偏向鎖時(shí),偏向鎖會(huì)自動(dòng)升級(jí)為輕量級(jí)鎖。2、輕量級(jí)鎖
適用場(chǎng)景:適用于多個(gè)線(xiàn)程交替執(zhí)行同步塊的情況,競(jìng)爭(zhēng)不激烈的場(chǎng)景。獲取鎖的代價(jià):獲取輕量級(jí)鎖的代價(jià)相對(duì)較低,需要進(jìn)行CAS操作。競(jìng)爭(zhēng)情況:當(dāng)競(jìng)爭(zhēng)激烈或者CAS操作失敗時(shí),輕量級(jí)鎖會(huì)自動(dòng)升級(jí)為重量級(jí)鎖。3、重量級(jí)鎖
適用場(chǎng)景:適用于競(jìng)爭(zhēng)激烈的場(chǎng)景,多個(gè)線(xiàn)程頻繁爭(zhēng)奪同一個(gè)鎖的情況。獲取鎖的代價(jià):獲取重量級(jí)鎖的代價(jià)相對(duì)較高,需要進(jìn)行線(xiàn)程阻塞和喚醒操作。競(jìng)爭(zhēng)情況:當(dāng)持有鎖的線(xiàn)程釋放鎖后,等待隊(duì)列中的線(xiàn)程按照FIFO順序競(jìng)爭(zhēng)鎖的獲取。需要注意的是,鎖的升級(jí)過(guò)程是自動(dòng)進(jìn)行的,開(kāi)發(fā)者無(wú)需手動(dòng)干預(yù)。JVM會(huì)根據(jù)鎖的競(jìng)爭(zhēng)情況自動(dòng)切換鎖的狀態(tài),以平衡性能和線(xiàn)程公平性。
在實(shí)際開(kāi)發(fā)中,選擇合適的鎖取決于具體的應(yīng)用場(chǎng)景和線(xiàn)程競(jìng)爭(zhēng)情況。如果線(xiàn)程之間的競(jìng)爭(zhēng)非常激烈,可以考慮使用其他更高級(jí)的鎖機(jī)制,如并發(fā)包中提供的ReentrantLock、ReadWriteLock等,它們提供了更細(xì)粒度的控制和更高的并發(fā)性能。