Java中Synchronized的原理是什么

本篇文章為大家展示了Java中Synchronized的原理是什么,內(nèi)容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細(xì)介紹希望你能有所收獲。

公司主營業(yè)務(wù):網(wǎng)站設(shè)計制作、成都做網(wǎng)站、移動網(wǎng)站開發(fā)等業(yè)務(wù)。幫助企業(yè)客戶真正實(shí)現(xiàn)互聯(lián)網(wǎng)宣傳,提高企業(yè)的競爭能力。創(chuàng)新互聯(lián)公司是一支青春激揚(yáng)、勤奮敬業(yè)、活力青春激揚(yáng)、勤奮敬業(yè)、活力澎湃、和諧高效的團(tuán)隊(duì)。公司秉承以“開放、自由、嚴(yán)謹(jǐn)、自律”為核心的企業(yè)文化,感謝他們對我們的高要求,感謝他們從不同領(lǐng)域給我們帶來的挑戰(zhàn),讓我們激情的團(tuán)隊(duì)有機(jī)會用頭腦與智慧不斷的給客戶帶來驚喜。創(chuàng)新互聯(lián)公司推出新絳免費(fèi)做網(wǎng)站回饋大家。

原本的問題

Synchronized是基于底層操作系統(tǒng)的 Mutex Lock 實(shí)現(xiàn)的,每次獲取鎖和釋放鎖的操作都會帶來用戶態(tài)內(nèi)核態(tài)的切換,從而增加系統(tǒng)性能開銷。

因此,在鎖競爭激烈的情況下,Synchronized同步鎖在性能上就表現(xiàn)得非常糟糕,它也常被大家稱為重量級鎖

到了 JDK1.5 版本,并發(fā)包中新增了 Lock 接口來實(shí)現(xiàn)鎖功能,它提供了與 Synchronized 關(guān)鍵字類似的同步功能,只是在使用時需要顯示獲取鎖和釋放鎖。

在單個線程重復(fù)申請鎖的情況下,JDK1.5 版本的 Lock 性能要比 Synchronized 鎖的性能好很多,也就是當(dāng)時的 Synchronized 并不具備可重入鎖的功能。

那么當(dāng)時的 Synchronized 是怎么實(shí)現(xiàn)的?又為什么不具備可重入的功能呢?

Synchronized原理

JVM 中的同步是基于進(jìn)入和退出管程(Monitor)對象實(shí)現(xiàn)的。每個對象實(shí)例都會有一個 Monitor,Monitor 可以和對象一起創(chuàng)建、銷毀。

當(dāng)多個線程同時訪問一段同步代碼時,多個線程會先被存放在EntryList集合(也可稱為阻塞隊(duì)列)中,處于BLOCKED狀態(tài)的線程,都會被加入到該列表。

接下來當(dāng)線程獲取到對象的 Monitor 時,Monitor 是依靠底層操作系統(tǒng)的 Mutex Lock 來實(shí)現(xiàn)互斥的,線程申請 Mutex 成功,則持有該 Mutex,其它線程將無法獲取到該 Mutex。

如果線程調(diào)用 wait() 方法,就會釋放當(dāng)前持有的 Mutex,并且該線程會進(jìn)入WaitSet集合(也可稱為等待隊(duì)列)中,等待下一次被喚醒。此時線程會處于WAITING或者TIMEDWAITING狀態(tài),

如果當(dāng)前線程順利執(zhí)行完方法,也將釋放 Mutex。

總的來說,就是同步鎖在這種實(shí)現(xiàn)方式中,因 Monitor 是依賴于底層的操作系統(tǒng)實(shí)現(xiàn),存在用戶態(tài)內(nèi)核態(tài)之間的切換(可以理解為上下文切換),所以增加了性能開銷。

鎖升級

為了提升性能,JDK1.6 引入了偏向鎖、輕量級鎖、重量級鎖概念,來減少鎖競爭帶來的上下文切換,而正是新增的Java對象頭實(shí)現(xiàn)了鎖升級功能。

所謂鎖升級,就是指

>Synchronized 同步鎖初始為偏向鎖,隨著線程競爭越來越激烈,偏向鎖升級到輕量級鎖,最終升級到重量級鎖。

偏向鎖

偏向鎖主要用來優(yōu)化同一線程多次申請同一個鎖的競爭,也就是現(xiàn)在的Synchronized鎖實(shí)際已經(jīng)擁有了可重入鎖的功能。

為什么要有偏向鎖?因?yàn)樵谖覀兊膽?yīng)用中,可能大部分時間是同一個線程競爭鎖資源(比如單線程操作一個線程安全的容器),如果這個線程每次都要獲取鎖和釋放鎖,那么就在不斷的從內(nèi)核態(tài)用戶態(tài)之間切換。

那么有了偏向鎖,當(dāng)一個線程再次訪問這個同步代碼或方法時,該線程只需去對象頭中去判斷一下是否當(dāng)前線程是否持有該偏向鎖就可以了。

一旦出現(xiàn)其它線程競爭鎖資源時,偏向鎖就會被撤銷。偏向鎖的撤銷需要等待全局安全點(diǎn)(JVM的stop the world),暫停持有該鎖的線程,同時檢查該線程是否還在執(zhí)行該方法,如果是,則升級鎖,反之則被其它線程搶占。

輕量級鎖

當(dāng)有另外一個線程競爭獲取這個鎖時,由于該鎖已經(jīng)是偏向鎖,當(dāng)發(fā)現(xiàn)對象頭中的線程 ID 不是自己的線程 ID,就會進(jìn)行 CAS 操作獲取鎖,如果獲取成功,直接替換對象頭中的線程 ID 為自己的 ID,該鎖會保持偏向鎖狀態(tài);如果獲取鎖失敗,代表當(dāng)前鎖有一定的競爭,偏向鎖將升級為輕量級鎖。

輕量級鎖適用于線程交替執(zhí)行同步塊的場景,絕大部分的鎖在整個同步周期內(nèi)都不存在長時間的競爭。

輕量級鎖也支持自旋,因此其他線程再次爭搶時,如果CAS失敗,將不再會進(jìn)入阻塞狀態(tài),而是不斷自旋。

之所以自旋更好,是因?yàn)橹罢f了,默認(rèn)線程持有鎖的時間都不會太長,如果線程被掛起阻塞可能代價會更高。

如果自旋鎖重試之后搶鎖依然失敗,那么同步鎖就會升級至重量級鎖。

重量級鎖

在這個狀態(tài)下,未搶到鎖的線程都會進(jìn)入 Monitor,之后會被阻塞在WaitSet集合中,也就變成了優(yōu)化之前的Synchronized鎖

JVM參數(shù)優(yōu)化

偏向鎖升級為輕量級鎖時,會發(fā)生stop the world,如果系統(tǒng)常常是多線程競爭,那么禁止偏向鎖也許是更好的選擇,可以通過以下JVM參數(shù)進(jìn)行優(yōu)化:

// 關(guān)閉偏向鎖(默認(rèn)打開)
-XX:-UseBiasedLocking
// 設(shè)置重量級鎖
-XX:+UseHeavyMonitors

輕量級鎖擁有自旋鎖的功能,那么如果線程持有鎖的時間很長,那么競爭的線程也會常常處于自旋狀態(tài),占用系統(tǒng) CPU ,增加系統(tǒng)開銷,那么此時關(guān)閉自旋鎖的優(yōu)化可以更好一些:

-XX:-UseSpinning

上述內(nèi)容就是Java中Synchronized的原理是什么,你們學(xué)到知識或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識儲備,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。

分享標(biāo)題:Java中Synchronized的原理是什么
URL地址:http://muchs.cn/article26/ihcijg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供App開發(fā)、商城網(wǎng)站靜態(tài)網(wǎng)站、云服務(wù)器、企業(yè)網(wǎng)站制作做網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

手機(jī)網(wǎng)站建設(shè)