同步方法與靜態同步方法各自的鎖對象是誰
synchronized實現同步的基礎:Java中的每一個對象都可以作為鎖。
具體表現為以下3種形式。
對於普通同步方法,鎖是當前實例對象。
對於靜態同步方法,鎖是當前類的Class對象。
對於同步方法塊,鎖是Synchonized括號里配置的對象。
解釋:
也就是說如果一個實例對象的非靜態同步方法獲取鎖后,該實例對象的其他非靜態同步方法必須等待獲取鎖的方法釋放鎖后才能獲取鎖, 可是別的實例對象的非靜態同步方法因為跟該實例對象的非靜態同步方法用的是不同的鎖, 所以毋須等待該實例對象已獲取鎖的非靜態同步方法釋放鎖就可以獲取他們自己的鎖。
所有的靜態同步方法用的也是同一把鎖——類對象本身, 這兩把鎖是兩個不同的對象,所以靜態同步方法與非靜態同步方法之間是不會有競態條件的。 但是一旦一個靜態同步方法獲取鎖后,其他的靜態同步方法都必須等待該方法釋放鎖后才能獲取鎖,
結論:
普通同步方法,鎖是當前實例對象。
不同的實例對象調用非靜態同步方法不存在競態關系
同一個實例對象調用非靜態同步方法時存在競態關系
靜態同步方法,鎖是當前類的Class對象。
調用靜態同步方法和其他靜態方法存在競態關系
與非靜態方法不存在競態關系
演示代碼(運行看效果)
public class SyncMethodTest { public static void main(String[] args) { //不同的實例對象,調用同步方法時各自持有自己的鎖,不存在競爭關系 SynEntity syn = new SynEntity(); SynEntity synT = new SynEntity(); //靜態同步方法獲取鎖后,因為用的是同一把鎖(類對象本身),其他靜態同步方法都必須等待該方法釋放鎖 new Thread(() -> { SynEntity.method1(); }).start(); new Thread(() -> { SynEntity.method2(); }).start(); new Thread(() -> { syn.method3(); }).start(); new Thread(() -> { synT.method3(); }).start(); new Thread(() -> { syn.method4(); }).start(); } }
public class SynEntity { public synchronized static void method1() { System.out.println("靜態方法method1執行開始"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("靜態方法method1執行結束"); } public synchronized static void method2() { System.out.println("靜態方法method2執行開始"); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("靜態方法method2執行結束"); } public synchronized void method3() { System.out.println("普通方法method3執行開始"); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("普通方法method3執行結束"); } public synchronized void method4() { System.out.println("普通方法method4執行開始"); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("普通方法method4執行結束"); } }
參考文檔地址1:
