知了堂Java | Java基礎面試題(7)
23.Synchronized的原理是什么?
Synchronized是由JVM實現(xiàn)的一種實現(xiàn)互斥同步的方式,查看被Synchronized修飾過的程序塊編譯后的 字節(jié)碼,會發(fā)現(xiàn),被Synchronized修飾過的程序塊,在編譯前后被編譯器生成了monitorenter和 monitorexit兩個字節(jié)碼指令。?
在虛擬機執(zhí)行到monitorenter指令時,首先要嘗試獲取對象的鎖:如果這個對象沒有鎖定,或者當前線 程已經(jīng)擁有了這個對象的鎖,把鎖的計數(shù)器+1; 當執(zhí)行monitorexit指令時,將鎖計數(shù)器-1;當計數(shù)器 為0時,鎖就被釋放了。
如果獲取對象失敗了,那當前線程就要阻塞等待,直到對象鎖被另外一個線程 釋放為止。 Java中Synchronize通過在對象頭設置標志,達到了獲取鎖和釋放鎖的目的。?
24.為什么說Synchronized是非公平鎖?
非公平主要表現(xiàn)在獲取鎖的行為上,并非是按照申請鎖的時間前后給等待線程分配鎖的,每當鎖被釋放 后,任何一個線程都有機會競爭到鎖,這樣做的目的是為了提高執(zhí)行性能,缺點是可能會產(chǎn)生線程饑餓 現(xiàn)象?
25.Synchronized和ReentrantLock的異同?
synchronized:
是java內置的關鍵字,它提供了一種獨占的加鎖方式。synchronized的獲取和釋放鎖 由JVM實現(xiàn),用戶不需要顯示的釋放鎖,非常方便。然而synchronized也有一些問題: 當線程嘗試獲取 鎖的時候,如果獲取不到鎖會一直阻塞。 如果獲取鎖的線程進入休眠或者阻塞,除非當前線程異常,否 則其他線程嘗試獲取鎖必須一直等待
ReentrantLock:?
ReentrantLock是Lock的實現(xiàn)類,是一個互斥的同步鎖。ReentrantLock是JDK 1.5 之后提供的API層面的互斥鎖,需要lock()和unlock()方法配合try/finally語句塊來完成,等待可中斷避 免,出現(xiàn)死鎖的情況(如果別的線程正持有鎖,會等待參數(shù)給定的時間,在等待的過程中,如果獲取了 鎖定,就返回true,如果等待超時,返回false) 公平鎖與非公平鎖多個線程等待同一個鎖時,必須按照申請鎖的時間順序獲得鎖,Synchronized鎖非公 平鎖,ReentrantLock默認的構造函數(shù)是創(chuàng)建的非公平鎖,可以通過參數(shù)true設為公平鎖,但公平鎖表 現(xiàn)的性能不是很好?
從功能角度:
ReentrantLock 比 Synchronized的同步操作更精細(因為可以像普通對象一樣使用), 甚至實現(xiàn) Synchronized沒有的高級功能 等待可中斷當持有鎖的線程長期不釋放鎖的時候,正在等待的線程可以選擇放棄等待,對處理執(zhí)行 時間非常長的同步塊很有用。 帶超時的獲取鎖嘗試在指定的時間范圍內獲取鎖,如果時間到了仍然無法獲取則返回。 可以判斷是否有線程在排隊等待獲取鎖。 可以響應中斷請求與Synchronized不同,當獲取到鎖的線程被中斷時,能夠響應中斷,中斷異常將會 被拋出,同時鎖會被釋放。 可以實現(xiàn)公平鎖
從鎖釋放角度:?
Synchronized在JVM層面上實現(xiàn)的,不但可以通過一些監(jiān)控工具監(jiān)控 Synchronized的 鎖定,而且在代碼執(zhí)行出現(xiàn)異常時,JVM會自動釋放鎖定,但是使用Lock則不行,Lock是通過代碼實現(xiàn) 的,要保證鎖定一定會被釋放,就必須將 unLock()放到 finally{}中
從性能角度:
Synchronized早期實現(xiàn)比較低效,對比 ReentrantLock,大多數(shù)場景性能都相差較大。但 是在Java6中對其進行了非常多的改進, 在競爭不激烈時:Synchronized的性能要優(yōu)于 ReetrantLock 在高競爭情況下:Synchronized的性能會下降幾十倍,但是 ReetrantLock的性能能維持常態(tài)
今日分享就到這啦。請持續(xù)關注我們,帶你了解更多Java相關干貨知識。?