java虛擬機 synchronized鎖優化

自旋鎖與自適應自旋

互斥同步的時候,掛起線程和恢復線程的操作都需要轉入內核態中完成,這些操作給系統的併發帶來很大壓力。同步虛擬機團隊發現許多應用上鎖定狀態的維持時間很短,爲了這段時間去掛起和恢復線程並不值得。所以當一個線程請求另一個線程的鎖時,我們可以讓請求線程稍等一下,但不放棄處理器的執行時間,看看持有鎖的線程是否很快就會釋放鎖,我們只需讓請求線程執行一個忙循環(自旋),這就是所謂的自旋鎖。

自旋等待的時間是有限度的,因爲如果鎖佔用時間很長,那麼自旋的線程只會白白消耗處理器資源,帶來性能上的浪費,所以在JDK1.6引入了自適應的自旋鎖,自適應的自旋鎖自旋時間不再固定,而是由前一次在同一個鎖上的自旋時間及鎖的擁有者的狀態來決定,如果在同一個鎖上,自旋等待剛剛獲得成功,並且持有鎖的線程正在運行,那麼虛擬機就會認爲這次自旋也很有可能獲得成功,進而它將允許自旋等待持續相對更長的時間,比如100個循環,對於自旋很少成功的鎖,以後獲取這個鎖將可能省略掉自旋過程。

JDK1.6後鎖自旋默認開啓。


鎖消除

鎖消除是指虛擬機即時編譯器在運行時,對一些代碼上要求同步,但被檢查到不可能存在共享數據競爭的鎖進行消除。如果判斷在一段代碼中,堆上的所有數據都不會逃逸出去從而被其他線程訪問到,那就可以把它們當作棧上數據對待,認爲它們是線程私有的,同步加鎖自然就無須進行


鎖粗化

我們編寫代碼時,推薦將同步塊的作用範圍限制得儘量小——只在共享的實際作用域才進行同步,這樣是爲了使得需要同步的操作數量儘可能變小,如果存在鎖競爭,那等待鎖的線程也能儘快拿到鎖。

如果一系列的連續操作都對同一個對象反覆加鎖和解鎖,甚至加鎖操作是出現在循環體中,即時沒有線程競爭,頻繁進行互斥同步操作也會導致不必要的性能損耗。

如果虛擬機探測到有這樣一串零碎的操作都對同一個對象加鎖,將會把加鎖同步的範圍擴展(粗化)到整個操作序列的外部。即擴展到對象第一次加鎖前和最後一次加鎖後。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章