分享一下自己去面字節的經歷,我自己本科是普通211,在小廠幹了剛滿兩年,但是感覺作為一個程式設計師還是要趁早去大廠,剛拿到字節Offer。因為同時在工作也沒時間系統複習,面試前主要突擊了一下並發編程那塊內容,沒想到都被問到了!
終面的時候問了我多線程+高並發+CAS+鎖+線程池底層。一般我們對鎖的種類都比較了解,沒想到字節終面問了一個問題:鎖有哪些狀態?都有哪些優缺點?要不是突擊準備的時候看了一下這一塊,還真有點答不全。
下面就分享一下我自己整理的關於鎖的狀態的知識點筆記!篇幅有限,如果想看完整個人面經、筆記梳理和Java架構資料分享(200+頁PDF),私信我就可以發給你哈~
任何對象都有一個monitor與之關聯。同步代碼塊在編譯後會在開始位置插入monitorenter,在結束和異常處插入monitorexit,前者嘗試獲取對象的monitor。
對象的鎖信息,存在對象頭的mark word中。
在java1.6之前使用synchronized獲取和釋放鎖的開銷較大,性能比較差。為減少獲得和釋放鎖帶來的性能消耗引入偏向鎖和輕量級鎖,所以1.6及以後它的性能並不比lock差。
對象頭中鎖的狀態隨著競爭程度從低到高分為 無鎖狀態、偏向鎖狀態、輕量級鎖狀態、重量級鎖狀態。鎖的狀態只能升級不能降級。
線程獲取到鎖時,會在對象頭記錄鎖偏向的線程ID,後續進出同步塊不需要cas來加鎖和解鎖,只需測試頭裡面是否有指向當前線程的偏向鎖。其他線程嘗試cas替換偏向鎖的線程ID,成功則獲得偏向鎖,失敗則開始撤銷偏向鎖,暫停原持有偏向鎖的線程,若原線程已退出同步塊或未活動,則獲取成功,否則升級到輕量級鎖狀態。
優點:加鎖解鎖不需要額外消耗
缺點:存在競爭會帶來鎖撤銷的消耗;適用於只有一個線程進入同步塊的場景。
執行同步塊之前拷貝mark word到棧幀的鎖記錄中,然後cas將對象頭的mark word替換為指向鎖記錄的指針,若成功則獲取到鎖,若失敗則自旋獲取鎖。自旋一定次數還沒獲取到鎖,升級為重量級鎖。釋放鎖時會cas把棧幀中的mark word替換回對象頭,成功表示沒有競爭,失敗則升級為重量級鎖,競爭線程會進入阻塞,當前線程會釋放鎖並喚醒等待線程。
優點:競爭線程不用阻塞,提高響應速度
缺點:一直獲取不到鎖,自旋會消耗cpu;適用於無實際競爭或偶爾有競爭,追求響應時間,同步塊執行很快的場景。
優點:競爭線程阻塞不會消耗cpu
缺點:線程阻塞相應慢;適用於有實際競爭,追求吞吐量,同步塊執行時間較長。
看到這裡,你Get鎖狀態的知識點了嗎?
整理總結不易,如果覺得這篇文章有幫助的話,歡迎轉發、收藏,給我一些鼓勵~
有想看的內容或者建議,敬請留言!
最近利用空餘時間整理了一些精選Java架構學習視頻和大廠項目底層知識點,需要的同學歡迎私信我發給你~一起學習進步!有任何問題也歡迎交流~
Java日記本,每日存檔超實用的技術乾貨學習筆記,每天陪你前進一點點~