13張圖,深入理解Synchronized

{"type":"doc","content":[{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"前言","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Java併發編程系列第二篇","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Synchronized","attrs":{}}],"attrs":{}},{"type":"text","text":",文章風格依然是圖文並茂,通俗易懂,本文帶讀者們由淺入深理解","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Synchronized","attrs":{}}],"attrs":{}},{"type":"text","text":",讓讀者們也能與面試官瘋狂對線。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在併發編程中","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Synchronized","attrs":{}}],"attrs":{}},{"type":"text","text":"一直都是元老級的角色,","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Jdk 1.6","attrs":{}}],"attrs":{}},{"type":"text","text":"以前大家都稱呼它爲重量級鎖,相對於","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"J U C","attrs":{}}],"attrs":{}},{"type":"text","text":"包提供的","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Lock","attrs":{}}],"attrs":{}},{"type":"text","text":",它會顯得笨重,不過隨着","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Jdk 1.6","attrs":{}}],"attrs":{}},{"type":"text","text":"對","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Synchronized","attrs":{}}],"attrs":{}},{"type":"text","text":"進行各種優化後,","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Synchronized","attrs":{}}],"attrs":{}},{"type":"text","text":"性能已經非常快了。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"內容大綱","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/13/131a6ad61551000ff108ec9a9da80417.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"Synchronized使用方式","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Synchronized","attrs":{}}],"attrs":{}},{"type":"text","text":"是","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Java","attrs":{}}],"attrs":{}},{"type":"text","text":"提供的","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"同步關鍵字","attrs":{}},{"type":"text","text":",在多線程場景下,對共享資源代碼段進行讀寫操作(","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"必須包含寫操作,光讀不會有線程安全問題,因爲讀操作天然具備線程安全特性","attrs":{}},{"type":"text","text":"),可能會出現線程安全問題,我們可以使用","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Synchronized","attrs":{}}],"attrs":{}},{"type":"text","text":"鎖定共享資源代碼段,達到","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"互斥","attrs":{}},{"type":"text","text":"(","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"mutualexclusion","attrs":{}}],"attrs":{}},{"type":"text","text":")效果,保證線程安全。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"共享資源代碼段又稱爲","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"臨界區","attrs":{}},{"type":"text","text":"(","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"critical section","attrs":{}}],"attrs":{}},{"type":"text","text":"),保證","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"臨界區互斥","attrs":{}},{"type":"text","text":",是指執行","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"臨界區","attrs":{}},{"type":"text","text":"(","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"critical section","attrs":{}}],"attrs":{}},{"type":"text","text":")的只能有一個線程執行,其他線程阻塞等待,達到排隊效果。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/6e/6e7ee8d72af4ff05b4c6d8d18d7d2fd8.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Synchronized","attrs":{}}],"attrs":{}},{"type":"text","text":"的食用方式有三種","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"修飾普通函數,監視器鎖(","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"monitor","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":")便是對象實例(","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"this","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":")","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"修飾靜態靜態函數,視器鎖(","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"monitor","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":")便是對象的","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"Class","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"實例(每個對象只有一個","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"Class","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"實例)","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"修飾代碼塊,監視器鎖(","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"monitor","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":")是指定對象實例","attrs":{}}]}]}],"attrs":{}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"普通函數","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"普通函數使用","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Synchronized","attrs":{}}],"attrs":{}},{"type":"text","text":"的方式很簡單,在","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"訪問權限修飾符","attrs":{}},{"type":"text","text":"與","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"函數返回類型","attrs":{}},{"type":"text","text":"間加上","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Synchronized","attrs":{}}],"attrs":{}},{"type":"text","text":"。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/48/48d37b9f3d3c6de5ff062cba9e4c4ebc.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"多線程場景下,","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"thread","attrs":{}}],"attrs":{}},{"type":"text","text":"與","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"threadTwo","attrs":{}}],"attrs":{}},{"type":"text","text":"兩個線程執行","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"incr","attrs":{}}],"attrs":{}},{"type":"text","text":"函數,","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"incr","attrs":{}}],"attrs":{}},{"type":"text","text":"函數作爲","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"共享資源代碼段","attrs":{}},{"type":"text","text":"被多線程","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"讀寫操作","attrs":{}},{"type":"text","text":",我們將它稱爲","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"臨界區","attrs":{}},{"type":"text","text":",爲了保證","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"臨界區互斥","attrs":{}},{"type":"text","text":",使用","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Synchronized","attrs":{}}],"attrs":{}},{"type":"text","text":"修飾","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"incr","attrs":{}}],"attrs":{}},{"type":"text","text":"函數即可。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"public class SyncTest {\n\n private int j = 0;\n \n /**\n * 自增方法\n */\n public synchronized void incr(){\n //臨界區代碼--start\n for (int i = 0; i < 10000; i++) {\n j++;\n }\n //臨界區代碼--end\n }\n\n public int getJ() {\n return j;\n }\n}\n\npublic class SyncMain {\n\n public static void main(String[] agrs) throws InterruptedException {\n SyncTest syncTest = new SyncTest();\n Thread thread = new Thread(() -> syncTest.incr());\n Thread threadTwo = new Thread(() -> syncTest.incr());\n thread.start();\n threadTwo.start();\n thread.join();\n threadTwo.join();\n //最終打印結果是20000,如果不使用synchronized修飾,就會導致線程安全問題,輸出不確定結果\n System.out.println(syncTest.getJ());\n }\n\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"代碼十分簡單,","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"incr","attrs":{}}],"attrs":{}},{"type":"text","text":"函數被","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"synchronized","attrs":{}}],"attrs":{}},{"type":"text","text":"修飾,函數邏輯是對","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"j","attrs":{}}],"attrs":{}},{"type":"text","text":"進行","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"10000","attrs":{}}],"attrs":{}},{"type":"text","text":"次累加,兩個線程執行","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"incr","attrs":{}}],"attrs":{}},{"type":"text","text":"函數,最後輸出","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"j","attrs":{}}],"attrs":{}},{"type":"text","text":"結果。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"被","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"synchronized","attrs":{}}],"attrs":{}},{"type":"text","text":"修飾函數我們簡稱","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"同步函數","attrs":{}},{"type":"text","text":",線程執行稱","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"同步函數","attrs":{}},{"type":"text","text":"前,需要先獲取監視器鎖,簡稱鎖,獲取鎖成功才能執行","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"同步函數","attrs":{}},{"type":"text","text":",","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"同步函數","attrs":{}},{"type":"text","text":"執行完後,","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"線程會釋放鎖並通知喚醒其他線程獲取鎖","attrs":{}},{"type":"text","text":",獲取鎖失敗「","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"則阻塞並等待通知喚醒該線程重新獲取鎖","attrs":{}},{"type":"text","text":"」,","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"同步函數","attrs":{}},{"type":"text","text":"會以","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"this","attrs":{}}],"attrs":{}},{"type":"text","text":"作爲鎖,即當前對象,以上面的代碼段爲例就是","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"syncTest","attrs":{}}],"attrs":{}},{"type":"text","text":"對象。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/75/7535da7afa37df2b7e20c489e014df19.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"線程","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"thread","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"執行","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"syncTest.incr()","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"前","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"線程","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"thread","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"獲取鎖成功","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"線程","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"threadTwo","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"執行","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"syncTest.incr()","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"前","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"線程","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"threadTwo","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"獲取鎖失敗","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"線程","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"threadTwo","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"阻塞並等待喚醒","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"線程","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"thread","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"執行完","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"syncTest.incr()","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":",","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"j","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"累積到","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"10000","attrs":{}}],"attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"線程","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"thread","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"釋放鎖,通知喚醒","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"threadTwo","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"線程獲取鎖","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"線程","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"threadTwo","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"獲取鎖成功","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"線程","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"threadTwo","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"執行完","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"syncTest.incr()","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":",","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"j","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"累積到","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"20000","attrs":{}}],"attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"線程","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"threadTwo","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"釋放鎖","attrs":{}}]}]}],"attrs":{}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"靜態函數","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"靜態函數顧名思義,就是靜態的函數,它使用","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Synchronized","attrs":{}}],"attrs":{}},{"type":"text","text":"的方式與普通函數一致,唯一的區別是鎖的對象不再是","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"this","attrs":{}}],"attrs":{}},{"type":"text","text":",而是","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Class","attrs":{}}],"attrs":{}},{"type":"text","text":"對象。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/89/89e01864c01f7b83acc80cdb08bf1570.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"多線程執行","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Synchronized","attrs":{}}],"attrs":{}},{"type":"text","text":"修飾靜態函數代碼段如下。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"public class SyncTest {\n\n private static int j = 0;\n \n /**\n * 自增方法\n */\n public static synchronized void incr(){\n //臨界區代碼--start\n for (int i = 0; i < 10000; i++) {\n j++;\n }\n //臨界區代碼--end\n }\n\n public static int getJ() {\n return j;\n }\n}\n\npublic class SyncMain {\n\n public static void main(String[] agrs) throws InterruptedException {\n Thread thread = new Thread(() -> SyncTest.incr());\n Thread threadTwo = new Thread(() -> SyncTest.incr());\n thread.start();\n threadTwo.start();\n thread.join();\n threadTwo.join();\n //最終打印結果是20000,如果不使用synchronized修飾,就會導致線程安全問題,輸出不確定結果\n System.out.println(SyncTest.getJ());\n }\n\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Java","attrs":{}}],"attrs":{}},{"type":"text","text":"的靜態資源可以直接通過類名調用,靜態資源不屬於任何實例對象,它只屬於","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Class","attrs":{}}],"attrs":{}},{"type":"text","text":"對象,每個","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Class","attrs":{}}],"attrs":{}},{"type":"text","text":"在","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"J V M","attrs":{}}],"attrs":{}},{"type":"text","text":"中只有唯一的一個","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Class","attrs":{}}],"attrs":{}},{"type":"text","text":"對象,所以同步靜態函數會以","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Class","attrs":{}}],"attrs":{}},{"type":"text","text":"對象作爲鎖,後續獲取鎖、釋放鎖流程都一致。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"代碼塊","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"前面介紹的普通函數與靜態函數粒度都比較大,以整個函數爲範圍鎖定,現在想把範圍縮小、靈活配置,就需要使用","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"代碼塊","attrs":{}},{"type":"text","text":"了,使用","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"{}","attrs":{}}],"attrs":{}},{"type":"text","text":"符號定義範圍給","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Synchronized","attrs":{}}],"attrs":{}},{"type":"text","text":"修飾。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/73/7378672e9fa5d9b7984e06f64fbcdf4c.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"下面代碼中定義了","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"syncDbData","attrs":{}}],"attrs":{}},{"type":"text","text":"函數,","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"syncDbData","attrs":{}}],"attrs":{}},{"type":"text","text":"是一個僞同步數據的函數,耗時","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"2","attrs":{}}],"attrs":{}},{"type":"text","text":"秒,並且邏輯不涉及","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"共享資源讀寫操作","attrs":{}},{"type":"text","text":"(","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"非臨界區","attrs":{}},{"type":"text","text":"),另外還有兩個函數","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"incr","attrs":{}}],"attrs":{}},{"type":"text","text":"與","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"incrTwo","attrs":{}}],"attrs":{}},{"type":"text","text":",都是在自增邏輯前執行了","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"syncDbData","attrs":{}}],"attrs":{}},{"type":"text","text":"函數,只是使用","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Synchronized","attrs":{}}],"attrs":{}},{"type":"text","text":"的姿勢不同,一個是修飾在函數上,另一個是修飾在代碼塊上。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"public class SyncTest {\n\n private static int j = 0;\n\n\n /**\n * 同步庫數據,比較耗時,代碼資源不涉及共享資源讀寫操作。\n */\n public void syncDbData() {\n System.out.println(\"db數據開始同步------------\");\n try {\n //同步時間需要2秒\n Thread.sleep(2000);\n } catch (InterruptedException e) {\n e.printStackTrace();\n }\n System.out.println(\"db數據開始同步完成------------\");\n }\n\n //自增方法\n public synchronized void incr() {\n //start--臨界區代碼\n //同步庫數據\n syncDbData();\n for (int i = 0; i < 10000; i++) {\n j++;\n }\n //end--臨界區代碼\n }\n\n //自增方法\n public void incrTwo() {\n //同步庫數據\n syncDbData();\n synchronized (this) {\n //start--臨界區代碼\n for (int i = 0; i < 10000; i++) {\n j++;\n }\n //end--臨界區代碼\n }\n\n }\n\n public int getJ() {\n return j;\n }\n\n}\n\n\npublic class SyncMain {\n\n public static void main(String[] agrs) throws InterruptedException {\n //incr同步方法執行\n SyncTest syncTest = new SyncTest();\n Thread thread = new Thread(() -> syncTest.incr());\n Thread threadTwo = new Thread(() -> syncTest.incr());\n thread.start();\n threadTwo.start();\n thread.join();\n threadTwo.join();\n //最終打印結果是20000\n System.out.println(syncTest.getJ());\n\n //incrTwo同步塊執行\n thread = new Thread(() -> syncTest.incrTwo());\n threadTwo = new Thread(() -> syncTest.incrTwo());\n thread.start();\n threadTwo.start();\n thread.join();\n threadTwo.join();\n //最終打印結果是40000\n System.out.println(syncTest.getJ());\n }\n\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"先看看","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"incr","attrs":{}}],"attrs":{}},{"type":"text","text":"同步方法執行,流程和前面沒區別,只是","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Synchronized","attrs":{}}],"attrs":{}},{"type":"text","text":"鎖定的範圍太大,把","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"syncDbData()","attrs":{}}],"attrs":{}},{"type":"text","text":"也納入","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"臨界區","attrs":{}},{"type":"text","text":"中,多線程場景執行,會有性能上的浪費,因爲","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"syncDbData()","attrs":{}}],"attrs":{}},{"type":"text","text":"完全可以讓多線程","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"並行","attrs":{}},{"type":"text","text":"或","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"併發","attrs":{}},{"type":"text","text":"執行。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/1f/1f2966d17d22c14d43b0efd7f00e2b6a.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們通過代碼塊的方式,來縮小範圍,定義正確的","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"臨界區","attrs":{}},{"type":"text","text":",提升性能,目光轉到","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"incrTwo","attrs":{}}],"attrs":{}},{"type":"text","text":"同步塊執行,","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"incrTwo","attrs":{}}],"attrs":{}},{"type":"text","text":"函數使用修飾代碼塊的方式同步,只對自增代碼段進行鎖定。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/66/6630aede8a91e0080861d0a5adde3550.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"代碼塊同步方式除了靈活控制範圍外,還能做線程間的協同工作,因爲","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Synchronized ()","attrs":{}}],"attrs":{}},{"type":"text","text":"括號中能接收任何對象作爲鎖,所以可以通過","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Object","attrs":{}}],"attrs":{}},{"type":"text","text":"的","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"wait、notify、notifyAll","attrs":{}}],"attrs":{}},{"type":"text","text":"等函數,做多線程間的通信協同(本文不對線程通信協同做展開,主角是","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Synchronized","attrs":{}}],"attrs":{}},{"type":"text","text":",而且也不推薦去用這些方法,因爲","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"LockSupport","attrs":{}}],"attrs":{}},{"type":"text","text":"工具類會是更好的選擇)。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"wait:當前線程暫停,釋放鎖","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"notify:釋放鎖,喚醒調用了wait的線程(如果有多個隨機喚醒一個)","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"notifyAll:釋放鎖,喚醒調用了wait的所有線程","attrs":{}}]}]}],"attrs":{}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"Synchronized原理","attrs":{}}]},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":" public class SyncTest {\n\n private static int j = 0;\n\n\n /**\n * 同步庫數據,比較耗時,代碼資源不涉及共享資源讀寫操作。\n */\n public void syncDbData() {\n System.out.println(\"db數據開始同步------------\");\n try {\n //同步時間需要2秒\n Thread.sleep(2000);\n } catch (InterruptedException e) {\n e.printStackTrace();\n }\n System.out.println(\"db數據開始同步完成------------\");\n }\n\n //自增方法\n public synchronized void incr() {\n //start--臨界區代碼\n //同步庫數據\n syncDbData();\n for (int i = 0; i < 10000; i++) {\n j++;\n }\n //end--臨界區代碼\n }\n\n //自增方法\n public void incrTwo() {\n //同步庫數據\n syncDbData();\n synchronized (this) {\n //start--臨界區代碼\n for (int i = 0; i < 10000; i++) {\n j++;\n }\n //end--臨界區代碼\n }\n\n }\n\n public int getJ() {\n return j;\n }\n\n} \n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"爲了探究","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Synchronized","attrs":{}}],"attrs":{}},{"type":"text","text":"原理,我們對上面的代碼進行反編譯,輸出反編譯後結果,看看底層是如何實現的(","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"環境Java 11、win 10系統","attrs":{}},{"type":"text","text":")。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":" 只截取了incr與incrTwo函數內容\n \n public synchronized void incr();\n Code:\n 0: aload_0 \n 1: invokevirtual #11 // Method syncDbData:()V \n 4: iconst_0 \n 5: istore_1 \n 6: iload_1 \n 7: sipush 10000 \n 10: if_icmpge 27\n 13: getstatic #12 // Field j:I\n 16: iconst_1\n 17: iadd\n 18: putstatic #12 // Field j:I\n 21: iinc 1, 1\n 24: goto 6\n 27: return\n\n public void incrTwo(); \n Code:\n 0: aload_0\n 1: invokevirtual #11 // Method syncDbData:()V\n 4: aload_0\n 5: dup\n 6: astore_1\n 7: monitorenter //獲取鎖\n 8: iconst_0\n 9: istore_2\n 10: iload_2\n 11: sipush 10000\n 14: if_icmpge 31\n 17: getstatic #12 // Field j:I\n 20: iconst_1\n 21: iadd\n 22: putstatic #12 // Field j:I\n 25: iinc 2, 1\n 28: goto 10\n 31: aload_1\n 32: monitorexit //正常退出釋放鎖 \n 33: goto 41\n 36: astore_3\n 37: aload_1\n 38: monitorexit //異步退出釋放鎖 \n 39: aload_3\n 40: athrow\n 41: return\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"ps:對上面指令感興趣的讀者,可以百度或google一下“JVM 虛擬機字節碼指令表”","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"先看","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"incrTwo","attrs":{}}],"attrs":{}},{"type":"text","text":"函數,","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"incrTwo","attrs":{}}],"attrs":{}},{"type":"text","text":"是代碼塊方式同步,在反編譯後的結果中,我們發現存在","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"monitorenter","attrs":{}}],"attrs":{}},{"type":"text","text":"與","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"monitorexit","attrs":{}}],"attrs":{}},{"type":"text","text":"指令(","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"獲取鎖、釋放鎖","attrs":{}},{"type":"text","text":")。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"monitorenter","attrs":{}}],"attrs":{}},{"type":"text","text":"指令插入到同步代碼塊的開始位置,","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"monitorexit","attrs":{}}],"attrs":{}},{"type":"text","text":"指令插入到同步代碼塊的結束位置,","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"J V M","attrs":{}}],"attrs":{}},{"type":"text","text":"需要保證每一個 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"monitorenter","attrs":{}}],"attrs":{}},{"type":"text","text":"都有","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"monitorexit","attrs":{}}],"attrs":{}},{"type":"text","text":"與之對應。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"任何對象","attrs":{}},{"type":"text","text":"都有一個監視器鎖(","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"monitor","attrs":{}}],"attrs":{}},{"type":"text","text":")關聯,線程執行","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"monitorenter","attrs":{}}],"attrs":{}},{"type":"text","text":"指令時嘗試獲取","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"monitor","attrs":{}}],"attrs":{}},{"type":"text","text":"的所有權。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"如果","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"monitor","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"的進入數爲","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"0","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":",則該線程進入","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"monitor","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":",然後將進入數設置爲","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"1","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":",該線程爲","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"monitor","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"的所有者","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"如果線程已經佔有該","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"monitor","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":",重新進入,則","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"monitor","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"的進入數加","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"1","attrs":{}}],"attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"線程執行","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"monitorexit","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":",","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"monitor","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"的進入數-1,執行過多少次","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"monitorenter","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":",最終要執行對應次數的","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"monitorexit","attrs":{}}],"attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"如果其他線程已經佔用","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"monitor","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":",則該線程進入阻塞狀態,直到","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"monitor","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"的進入數爲0,再重新嘗試獲取","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"monitor","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"的所有權","attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"回過頭看","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"incr","attrs":{}}],"attrs":{}},{"type":"text","text":"函數,","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"incr","attrs":{}}],"attrs":{}},{"type":"text","text":"是普通函數方式同步,雖然在反編譯後的結果中沒有看到","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"monitorenter","attrs":{}}],"attrs":{}},{"type":"text","text":"與","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"monitorexit","attrs":{}}],"attrs":{}},{"type":"text","text":"指令,但是實際執行的流程與","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"incrTwo","attrs":{}}],"attrs":{}},{"type":"text","text":"函數一樣,通過","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"monitor","attrs":{}}],"attrs":{}},{"type":"text","text":"來執行,只不過它是一種隱式的方式來實現,最後放一張流程圖。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/fc/fc66b23cb89ca940c6ad9101cf5548d3.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"Synchronized優化","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Jdk 1.5","attrs":{}}],"attrs":{}},{"type":"text","text":"以後對","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Synchronized","attrs":{}}],"attrs":{}},{"type":"text","text":"關鍵字做了各種的優化,經過優化後","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Synchronized","attrs":{}}],"attrs":{}},{"type":"text","text":"已經變得越來越快了,這也是爲什麼官方建議使用","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Synchronized","attrs":{}}],"attrs":{}},{"type":"text","text":"的原因,具體的優化點如下。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"鎖粗化","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"鎖消除","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"鎖升級","attrs":{}}]}]}],"attrs":{}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"鎖粗化","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"互斥的臨界區","attrs":{}},{"type":"text","text":"範圍應該儘可能小,這樣做的目的是爲了使同步的操作數量儘可能縮小,縮短阻塞時間,如果存在鎖競爭,那麼等待鎖的線程也能儘快拿到鎖。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"但是加鎖解鎖也需要消耗資源,如果存在一系列的連續加鎖解鎖操作,可能會導致不必要的性能損耗,","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"鎖粗化","attrs":{}},{"type":"text","text":"就是將「","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"多個連續的加鎖、解鎖操作連接在一起","attrs":{}},{"type":"text","text":"」,擴展成一個範圍更大的鎖,避免頻繁的加鎖解鎖操作。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/e4/e4b668bc41040139f7a7e091c08a2960.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"J V M","attrs":{}}],"attrs":{}},{"type":"text","text":"會檢測到一連串的操作都對同一個對象加鎖(","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"for","attrs":{}}],"attrs":{}},{"type":"text","text":"循環","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"10000","attrs":{}}],"attrs":{}},{"type":"text","text":"次執行","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"j++","attrs":{}}],"attrs":{}},{"type":"text","text":",沒有鎖粗化就要進行","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"10000","attrs":{}}],"attrs":{}},{"type":"text","text":"次加鎖/解鎖),此時","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"J V M","attrs":{}}],"attrs":{}},{"type":"text","text":"就會將加鎖的範圍粗化到這一連串操作的外部(比如","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"for","attrs":{}}],"attrs":{}},{"type":"text","text":"循環體外),使得這一連串操作只需要加一次鎖即可。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"鎖消除","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Java","attrs":{}}],"attrs":{}},{"type":"text","text":"虛擬機在","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"JIT","attrs":{}}],"attrs":{}},{"type":"text","text":"編譯時(","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"可以簡單理解爲當某段代碼即將第一次被執行時進行編譯,又稱即時編譯","attrs":{}},{"type":"text","text":"),通過對運行上下文的掃描,經過逃逸分析(","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"對象在函數中被使用,也可能被外部函數所引用,稱爲函數逃逸","attrs":{}},{"type":"text","text":"),去除不可能存在共享資源競爭的鎖,通過這種方式消除沒有必要的鎖,可以節省毫無意義的時間消耗。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/09/094680238f44c254f269f98c16d7c07b.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"代碼中使用","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Object","attrs":{}}],"attrs":{}},{"type":"text","text":"作爲鎖,但是","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Object","attrs":{}}],"attrs":{}},{"type":"text","text":"對象的生命週期只在","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"incrFour()","attrs":{}}],"attrs":{}},{"type":"text","text":"函數中,並不會被其他線程所訪問到,所以在","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"J I T","attrs":{}}],"attrs":{}},{"type":"text","text":"編譯階段就會被優化掉(","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"此處的","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"Object","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"屬於沒有逃逸的對象","attrs":{}},{"type":"text","text":")。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"鎖升級","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Java","attrs":{}}],"attrs":{}},{"type":"text","text":"中每個對象都擁有對象頭,對象頭由","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Mark World","attrs":{}}],"attrs":{}},{"type":"text","text":" 、指向類的指針、以及數組長度三部分組成,本文,我們只需要關心","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Mark World","attrs":{}}],"attrs":{}},{"type":"text","text":" 即可,","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":" Mark World","attrs":{}}],"attrs":{}},{"type":"text","text":" 記錄了對象的","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"HashCode","attrs":{}}],"attrs":{}},{"type":"text","text":"、分代年齡和鎖標誌位信息。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"Mark World簡化結構","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/06/0647016ffe03270e54a877126d3cb325.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"讀者們只需知道,鎖的升級變化,體現在鎖對象的對象頭","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Mark World","attrs":{}}],"attrs":{}},{"type":"text","text":"部分,也就是說","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Mark World","attrs":{}}],"attrs":{}},{"type":"text","text":"的內容會隨着鎖升級而改變。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Java1.5","attrs":{}}],"attrs":{}},{"type":"text","text":"以後爲了減少獲取鎖和釋放鎖帶來的性能消耗,引入了","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"偏向鎖","attrs":{}},{"type":"text","text":"和","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"輕量級鎖","attrs":{}},{"type":"text","text":",","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Synchronized","attrs":{}}],"attrs":{}},{"type":"text","text":"的升級順序是 「","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"無鎖-->偏向鎖-->輕量級鎖-->重量級鎖,只會升級不會降級","attrs":{}},{"type":"text","text":"」","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"偏向鎖","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在大多數情況下,鎖總是由同一線程多次獲得,不存在多線程競爭,所以出現了偏向鎖,其目標就是在只有一個線程執行同步代碼塊時,降低獲取鎖帶來的消耗,提高性能(","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"可以通過J V M參數關閉偏向鎖:-XX:-UseBiasedLocking=false,關閉之後程序默認會進入輕量級鎖狀態","attrs":{}},{"type":"text","text":")。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"線程執行同步代碼或方法前,線程只需要判斷對象頭的","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Mark Word","attrs":{}}],"attrs":{}},{"type":"text","text":"中線程","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"ID","attrs":{}}],"attrs":{}},{"type":"text","text":"與當前線程","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"ID","attrs":{}}],"attrs":{}},{"type":"text","text":"是否一致,如果一致直接執行同步代碼或方法,具體流程如下","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/4a/4a10a6e21c484fb3be21fcd3b8e109e0.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"無鎖狀態,存儲內容「是否爲偏向鎖(","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"0","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":")」,鎖標識位","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"01","attrs":{}}],"attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"CAS","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"設置當前線程ID到","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"Mark Word","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"存儲內容中","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"是否爲偏向鎖","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"0","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":" => 是否爲偏向鎖","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"1","attrs":{}}],"attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"執行同步代碼或方法","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"偏向鎖狀態,存儲內容「是否爲偏向鎖(","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"1","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":")、線程ID」,鎖標識位","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"01","attrs":{}}],"attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"對比線程","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"ID","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"是否一致,如果一致執行同步代碼或方法,否則進入下面的流程","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"如果不一致,","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"CAS","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"將","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"Mark Word","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"的線程","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"ID","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"設置爲當前線程","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"ID","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":",設置成功,執行同步代碼或方法,否則進入下面的流程","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"CAS","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"設置失敗,證明存在多線程競爭情況,觸發撤銷偏向鎖,當到達全局安全點,偏向鎖的線程被掛起,偏向鎖升級爲輕量級鎖,然後在安全點的位置恢復繼續往下執行。","attrs":{}}]}]}],"attrs":{}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"輕量級鎖","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"輕量級鎖考慮的是競爭鎖對象的線程不多,持有鎖時間也不長的場景。因爲阻塞線程需要","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"C P U","attrs":{}}],"attrs":{}},{"type":"text","text":"從用戶態轉到內核態,代價較大,如果剛剛阻塞不久這個鎖就被釋放了,那這個代價就有點得不償失,所以乾脆不阻塞這個線程,讓它自旋一段時間等待鎖釋放。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當前線程持有的鎖是偏向鎖的時候,被另外的線程所訪問,偏向鎖就會升級爲輕量級鎖,其他線程會通過自旋的形式嘗試獲取鎖,不會阻塞,從而提高性能。輕量級鎖的獲取主要有兩種情況:① 當關閉偏向鎖功能時;② 多個線程競爭偏向鎖導致偏向鎖升級爲輕量級鎖。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/4a/4a70ca6d41ed62e92e2a0fff1c11100e.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"無鎖狀態,存儲內容「是否爲偏向鎖(","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"0","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":")」,鎖標識位","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"01","attrs":{}}],"attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"關閉偏向鎖功能時","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"CAS","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"設置當前線程棧中鎖記錄的指針到","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"Mark Word","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"存儲內容","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"鎖標識位設置爲","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"00","attrs":{}}],"attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"執行同步代碼或方法","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"釋放鎖時,還原來","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"Mark Word","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"內容","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"輕量級鎖狀態,存儲內容「線程棧中鎖記錄的指針」,鎖標識位","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"00","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"(存儲內容的線程是指\"持有輕量級鎖的線程\")","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"CAS","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"設置當前線程棧中鎖記錄的指針到","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"Mark Word","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"存儲內容,設置成功獲取輕量級鎖,執行同步塊代碼或方法,否則執行下面的邏輯","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"設置失敗,證明多線程存在一定競爭,線程自旋上一步的操作,自旋一定次數後還是失敗,輕量級鎖升級爲重量級鎖","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"Mark Word","attrs":{}}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"存儲內容替換成重量級鎖指針,鎖標記位","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"10","attrs":{}}],"attrs":{}}]}]}],"attrs":{}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"重量級鎖","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"輕量級鎖膨脹之後,就升級爲重量級鎖,重量級鎖是依賴操作系統的","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"MutexLock","attrs":{}}],"attrs":{}},{"type":"text","text":"(","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"互斥鎖","attrs":{}},{"type":"text","text":")來實現的,需要從用戶態轉到內核態,這個成本非常高,這就是爲什麼","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Java1.6","attrs":{}}],"attrs":{}},{"type":"text","text":"之前","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Synchronized","attrs":{}}],"attrs":{}},{"type":"text","text":"效率低的原因。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"升級爲重量級鎖時,鎖標誌位的狀態值變爲","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"10","attrs":{}}],"attrs":{}},{"type":"text","text":",此時","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Mark Word","attrs":{}}],"attrs":{}},{"type":"text","text":"中存儲內容的是重量級鎖的指針,等待鎖的線程都會進入阻塞狀態,下面是簡化版的鎖升級過程。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/4f/4f39fcc93208dc073796009af7b1b8b8.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"歷史好文推薦","attrs":{}}]},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://mp.weixin.qq.com/s/GR7lLGp9JH4bsAgQB3uLrw","title":"","type":null},"content":[{"type":"text","text":"由淺入深CAS,小白也能與BAT面試官對線","attrs":{}}]}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://mp.weixin.qq.com/s/48OLw2koXwrcJ5YOKSNmFw","title":"","type":null},"content":[{"type":"text","text":"小白也能看懂的Java內存模型","attrs":{}}]}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://mp.weixin.qq.com/s/woFmXOt5zOxidlkduIfruA","title":"","type":null},"content":[{"type":"text","text":"保姆級教學,22張圖揭開ThreadLocal","attrs":{}}]}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://mp.weixin.qq.com/s/jhOSjVyRA6rNKqVT2pKMIQ","title":"","type":null},"content":[{"type":"text","text":"進程、線程與協程傻傻分不清?一文帶你喫透!","attrs":{}}]}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://mp.weixin.qq.com/s/_ATueOBN4UM2bim_1hDBFQ","title":"","type":null},"content":[{"type":"text","text":"什麼是線程安全?一文帶你深入理解","attrs":{}}]}]}]}],"attrs":{}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"關於我","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這裏是阿星,一個熱愛技術的Java程序猿,公衆號 ","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"「程序猿阿星」","attrs":{}},{"type":"text","text":"裏將會定期分享操作系統、計算機網絡、Java、分佈式、數據庫等精品原創文章,2021,與您在 Be Better 的路上共同成長!。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/22/2205b202fa895835f7d7d99379308e9f.gif","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"非常感謝各位小哥哥小姐姐們能看到這裏,原創不易,文章有幫助可以關注、點個贊、分享與評論,都是支持(莫要白嫖)!","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"願你我都能奔赴在各自想去的路上,我們下篇文章見","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/cd/cd93a342bb6bb4cd5478beb9f35689e0.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章