Java多線程同步關鍵詞是經常使用的多線程同步手段。它能夠修飾靜態類方法,實例方法,或代碼塊。修飾static靜態方法時是對整個類加鎖。java
1、實現原理多線程
在JVM中對象內存分三塊區域,對象頭、實例數據、對齊填充數據。Java對象頭是實現synchronize鎖對象的基礎,它使用的鎖對象就是存儲在Java對象頭裏。JVM中用2個字節存儲對象頭,主要結構是由Mark Word和Class Metadata Address 組成,前者MarkWord裏存儲對象的hashcode、鎖信息、分代年齡、GC標誌等信息,後者存放類型指針,指向對象的類元數據。併發
從字節碼可知synchronized代碼塊的實現用的是mmonitorenter和monitorexit指令,synchronized方法同步是隱式同步,JVM從方法常量池中的方法表結構中的ACC_SYNCHRONIZED訪問標誌區分一個方法是不是同步方法。app
2、JVM鎖優化優化
JAVA6後JVM對同步關鍵詞進行優化,引入偏向鎖、自旋鎖、輕量級鎖等概念。對象頭中鎖狀態有無鎖狀態、偏向鎖、輕量級鎖和重量級鎖。操作系統
JVM在JIT編譯時經過上下文掃描,會去除不可能存在共享資源競爭的鎖,減小不必的請求鎖時間,好比方法內StringBuffer對象調用append時,JVM會自動將其消除。.net
JAVA6 默認引入了偏向鎖,若是一個線程獲取了鎖,則鎖就進入偏向模式,此時Mark Word的結構也從無鎖狀態變爲偏向鎖結構,當這個線程再請求鎖時無需作申請鎖等相關操做。若是每次申請鎖的線程都不相同則不該該用偏向鎖。線程
偏向鎖失敗後會先升級爲輕量級鎖,此時對象頭Mark Word結構變爲輕量級鎖結構,適應線程交替執行同步塊的場合,輕量級鎖使用的依據是「對大部分鎖,在整個同步週期內都不存在競爭」。若是存在同一時間訪問同一鎖的狀況,輕量級鎖就會失敗。指針
輕量級鎖失敗後虛擬機爲了不線程真實的在操做系統層面掛起,會進行自旋鎖優化手段。它基於大多數狀況下線程持有鎖的時間都不會太長,JVM讓想要獲取鎖的線程作一下子空循環若是獲得鎖就進入臨界區,若是失敗就在操做層面掛起,升級爲重量級鎖。code