日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

java 等待几秒_Java并发编程synchronized相关面试题总结

發布時間:2025/3/19 java 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java 等待几秒_Java并发编程synchronized相关面试题总结 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

說說自己對于synchronized關鍵字的了解

synchronized關鍵字用于解決多個線程之間訪問資源的同步性,synchronized關鍵字可以保證被它修飾的方法或者代碼塊在任意時刻只能有一個線程執行。

值得注意的是,在Java早期,JDK1.6之前,synchronized屬于重量級鎖,效率低下。

原因在于:

監視器鎖【monitor】依賴于底層操作系統的Mutex Lock實現,Java的線程是映射到操作系統的原生線程之上的。如果要掛起或喚醒一個線程,都需要操作系統幫忙完成,而操作系統實現線程之間的切換時需要從用戶態轉化到內核態,需要消耗比較長的時間。

但是,JDK1.6之后,Java官方從JVM層面對synchronized關鍵字進行了較大的優化,效率不可同日而語。主要的優化有:自旋鎖、適應性自旋鎖、鎖消除、鎖粗化、偏向鎖、輕量級鎖等技術來減少鎖操作的開銷。

synchronized關鍵字的三種使用

  • 修飾實例方法:作用于當前對象實例加鎖,進入同步代碼前要獲得?當前對象實例的鎖。

  • 修飾靜態方法:?也就是給當前類加鎖,會作用于類的所有對象實例 ,進入同步代碼前要獲得?當前 class 的鎖。

  • 注意:靜態成員不屬于任何一個實例對象,是類成員!因此,一個線程A調用一個實例對象的非靜態synchronized方法,一個線程B調用這個實例對象的所屬類的靜態synchronized方法,是被允許的。?因為訪問靜態 synchronized 方法占用的鎖是當前類的鎖,而訪問非靜態 synchronized 方法占用的鎖是當前實例對象鎖。

  • 修飾代碼塊?:給括號內配置的對象加鎖。synchronized(this|object) 表示進入同步代碼庫前要獲得給定對象的鎖。synchronized(類.class) 表示進入同步代碼前要獲得?當前 class 的鎖。

  • synchronized關鍵字的底層原理

    通過對.class文件的編譯可以發現:

    • 同步方法通過ACC_SYNCHRONIZED修飾。

    • 代碼塊同步使用monitorenter和monitorexit兩個指令實現。

    雖然兩者實現細節不同,但其實本質上都是JVM基于進入和退出Monitor對象來實現同步,JVM的要求如下:

    • monitorenter指令會在編譯后插入到同步代碼塊的開始位置,而monitorexit則會插入到方法結束和異常處。

    • 每個對象都有一個monitor與之關聯,且當一個monitor被持有之后,他會處于鎖定狀態。

    • 線程執行到monitorenter時,會嘗試獲取對象對應monitor的所有權。

    • 在獲取鎖時,如果對象沒被鎖定,或者當前線程已經擁有了該對象的鎖(可重進入,不會鎖死自己),將鎖計數器加一,執行monitorexit時,鎖計數器減一,計數為零則鎖釋放。

    • 獲取對象鎖失敗,則當前線程陷入阻塞,直到對象鎖被另外一個線程釋放。

    JDK1.6之后對synchronized關鍵字進行的優化

    優化:偏向鎖,輕量級鎖,自旋鎖,適應性自旋鎖,鎖消除,鎖粗化。

    鎖主要存在的四種狀態,依次是:無鎖狀態、偏向鎖狀態、輕量級鎖狀態、重量級鎖狀態,他們會隨著競爭的激烈而逐漸升級。注意鎖可以升級不可降級,這種策略是為了提高獲得鎖和釋放鎖的效率。

    Java對象頭的組成

    鎖存在于Java對象頭里,對象頭的組成部分:

    • Mark Word:存儲對象的hashCode或鎖信息等。

    • Class Metadata Address:存儲到對象類型數據的指針。

    • Array length:數組的長度(如果當前對象是數組)

    Java對象頭又存在于Java堆中,堆內存分為三部分:對象頭,實例數據和對齊填充。

    MarkWord的組成

    Java對象頭的MardWord中記錄了對象和鎖的相關信息,無鎖狀態下,Java對象頭里的Mark Word里默認存儲對象的HashCode、分代年齡和鎖標記位。在64位的JVM中,Mark Word為64 bit。

    在運行期間Mark Word里存儲的數據會隨著鎖標志位的變化而變化。鎖升級的功能也主要靠MarkWord中鎖標志位和是否偏向鎖標志完成。

    鎖升級的過程

    鎖升級的過程:無鎖,偏向鎖,輕量級鎖,重量級鎖

    偏向鎖

    HotSpot的作者經過研究發現,大多數情況下,鎖不僅不存在多線程競爭,而且總是由同一線程多次獲得,為了讓線程獲得鎖的代價更低而引入了偏向鎖。

    偏向鎖的適用場景

    偏向鎖主要用于優化:同一線程多次申請同一個鎖的競爭,在某些情況下,大部分時間都是同一個線程競爭鎖資源的。

    偏向鎖的加鎖

    主要流程:當一個線程訪問同步塊并獲取鎖時,會在對象頭和棧幀中的鎖記錄里存儲鎖偏向的線程ID,以后該線程在進入和退出同步塊時不需要進行CAS操作來加鎖和解鎖,只需簡單地測試一下對象頭的Mark Word里是否存儲著指向當前線程的偏向鎖。

    • 如果測試成功,表示線程已經獲得了鎖。

    • 如果測試失敗,則需要再測試一下Mark Word中偏向鎖的標識是否設置成1(表示當前是偏向鎖):如果沒有設置,則使用CAS競爭鎖。如果設置了,則嘗試使用CAS將對象頭的偏向鎖指向當前線程。

    偏向鎖的撤銷

    一旦出現其他線程競爭鎖資源時,偏向鎖就會被撤銷。偏向鎖的撤銷可能需要等待全局安全點【在這個時間點上沒有正在執行的字節碼】。

    • 首先暫停持有該鎖的線程,然后檢查持有偏向鎖的線程是否活著,如果線程不處于活動狀態,則將對象頭設置成無鎖狀態。

    • 如果持有偏向鎖的線程仍然活著,擁有偏向鎖的棧會被執行,遍歷偏向對象的鎖記錄,棧中的鎖記錄和對象頭的Mark Word要么重新偏向于其他線程,要么恢復到無鎖或者標記對象不適合作為偏向鎖,最后喚醒在暫停的線程。

    偏向鎖的關閉

    偏向鎖在Java 6和Java 7里是默認啟用的,但是它在應用程序啟動幾秒鐘之后才激活,如有必要可以使用JVM參數來關閉延遲:-XX:BiasedLockingStartupDelay=0。

    如果說通常處于競爭狀態,可以通過- XX:-UseBiasedLocking=false,進入輕量級鎖狀態。

    輕量級鎖

    如偏向鎖存在,如有另一線程競爭鎖,且對象頭MarkWord中的線程ID與當前線程ID不同,則該線程將會嘗試CAS操作獲取鎖,獲取失敗,代表鎖存在競爭,偏向鎖向輕量級鎖升級。

    輕量級鎖的加鎖

    • 線程在執行同步塊之前,JVM會先在當前線程的棧臺中創建用于存儲鎖記錄的空間【Displaced Mark Word】,并將對象頭中的Mark Word復制到鎖記錄中。

    • 然后線程嘗試使用CAS將對象頭中的Mark Word替換為指向鎖記錄的指針。替換成功,則當前線程獲得鎖。替換失敗,表示其他線程競爭鎖,當前線程嘗試使用自旋來獲取鎖。

    輕量級鎖的解鎖

    • 使用原子的CAS操作將【Displaced Mark Word】替換回對象頭。替換成功,表示沒有競爭發生。替換失敗,表示當前鎖存在競爭,鎖就會膨脹成重量級鎖。

    輕量級鎖的適用場景

    線程交替執行同步塊,絕大部分的鎖在整個同步周期內都不存在長時間的競爭。

    鎖的優缺點對比

    鎖優點缺點適用場景偏向鎖加鎖和解鎖不需要額外的消耗,和執行非同步方法比僅存在納秒級的差距。如果線程間存在鎖競爭, 會帶來額外的鎖撤銷的消耗。適用于只有一個線程訪問同步塊場景。輕量級鎖競爭的線程不會阻塞,提高了程序的響應速度。如果始終得不到所競爭的線程使用自旋會消耗CPU。追求響應時間。同步塊執行速度非???。重量級鎖線程競爭不使用自旋,不會消耗CPU。線程阻塞,響應時間緩慢。追求吞吐量。同步塊執行速度較長。

    總結

  • JVM在JDK 1.6中引入了分級鎖機制來優化synchronized

  • 當一個線程獲取鎖時,首先對象鎖成為一個偏向鎖這是為了避免在同一線程重復獲取同一把鎖時,用戶態和內核態頻繁切換

  • 如果有多個線程競爭鎖資源,鎖將會升級為輕量級鎖這適用于在短時間內持有鎖,且分鎖交替切換的場景輕量級鎖還結合了自旋鎖來避免線程用戶態與內核態的頻繁切換

  • 如果鎖競爭太激烈(自旋鎖失敗),同步鎖會升級為重量級鎖

  • 優化synchronized同步鎖的關鍵:減少鎖競爭應該盡量使synchronized同步鎖處于輕量級鎖或偏向鎖,這樣才能提高synchronized同步鎖的性能常用手段減少鎖粒度:降低鎖競爭減少鎖的持有時間,提高synchronized同步鎖在自旋時獲取鎖資源的成功率,避免升級為重量級鎖

  • 在鎖競爭激烈時,可以考慮禁用偏向鎖和禁用自旋鎖

  • synchronized關鍵字與ReentrantLock的區別

    共同點

    • 都是可重入鎖:自己可以再次獲取自己的內部鎖【避免一個線程獲取鎖之后,再次嘗試獲取鎖時造成的死鎖】。同一線程每次獲取鎖,計數器加一,釋放鎖,計數器減一,計數為0,代表完全釋放該鎖。

    不同點

    • synchronized依賴于JVM實現,ReentrantLock依賴于API。

    • 相比synchronized,ReentrantLock增加了一些高級功能。主要來說主要有三點:等待可中斷?: ReentrantLock提供了一種能夠中斷等待鎖的線程的機制,通過 lock.lockInterruptibly() 來實現這個機制。也就是說正在等待的線程可以選擇放棄等待,改為處理其他事情??蓪崿F公平鎖?: ReentrantLock可以指定是公平鎖還是非公平鎖。而synchronized只能是非公平鎖。所謂的公平鎖就是先等待的線程先獲得鎖。ReentrantLock默認情況是非公平的,可以通過 ReentrantLock類的ReentrantLock(boolean fair)構造方法來制定是否是公平的??蓪崿F選擇性通知(鎖可以綁定多個條件): synchronized關鍵字與wait()和notify()/notifyAll()方法相結合可以實現等待/通知機制。ReentrantLock類當然也可以實現,但是需要借助于Condition接口與newCondition()方法。

    如果感覺本文對你有幫助,點贊再看支持一下

    總結

    以上是生活随笔為你收集整理的java 等待几秒_Java并发编程synchronized相关面试题总结的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。