先上一段代碼,以下:java
List-1bash
public class Example2_synchronizer { @Test public void test1(){ synchronized (this){ int i=10; int j=i+1245; } } }
以後用在命令行輸入javap -v -p Example2_synchronizer,獲得以下片斷:性能
List-2 javap的結果優化
3: monitorenter 4: bipush 10 6: istore_2 7: iload_2 8: sipush 1245 11: iadd 12: istore_3 13: aload_1 14: monitorexit 15: goto 25 18: astore 4 20: aload_1 21: monitorexit 22: aload 4 24: athrow 25: return
這就是平時說的monitorenter、monitorexit,值得注意的是,有倆個monitorexit。爲何會有倆個monitorexit,由於:若是synchronized塊裏面的代碼拋出異常,那麼會執行1八、20、2一、2二、24編號處的指令,它是在釋放以前獲取的鎖。因此Java中synchronized中即便拋出異常,JVM也會釋放鎖,讓其它線程獲取該鎖。有點像咱們操做文件時try{}catch{}finally{關閉文件流}。this
來看下JVM 規範裏面給出的例子:.net
圖1 Java7的JVM規範中給出的例子 命令行
synchronized的實現時在JVM代碼中的,synchronized是經過對象的monitorenter/monitorexit來實現的,JVM中有三種不一樣的monitor實現,也就是咱們說的偏向鎖、輕量級鎖、重量級鎖。爲何要引入這麼多實現,是爲了該善性能。Java利用CAS(compare and swap),在對象頭部的mark word處設置線程ID,表示該對象被被線程佔有。線程
鎖的升級、降級,就是JVM優化synchronized運行的機制。鎖的升級是指從偏向鎖升級到輕量級鎖,從輕量級鎖升級到重量級鎖,如何作到的呢?待後面分析code
鎖共有4種狀態,級別從低到高依次爲:無狀態鎖,偏向鎖,輕量級鎖和重量級鎖狀態,因爲是4種狀態,因此用JVM中用2bits能夠表示鎖的狀態。對象
這篇博客也講的比較深刻:http://www.javashuo.com/article/p-rjpptcfl-cg.html