問題導入:如果一個線程調用了一個對象的同步方法,那么他還能不能在調用這個對象的另外一個同步方法呢?
這里就是synchronized鎖重入問題。
一.synchronized鎖重入
來看下面的代碼:
.這個是三個同步方法的類
public class Synfun_UseSynfun{ //同步方法1 public synchronized void fun1(){ System.out.println("我是一號同步方法"); this.fun2();//調用二號同步方法 } //同步方法2 public synchronized void fun2(){ System.out.println("我是二號同步方法"); this.fun3();//調用三號同步方法 } //同步方法3 public synchronized void fun3(){ System.out.println("我是三號同步方法"); } }
線程類,在run方法中調用一號同步方法:
public class SynThreadText extends Thread { private Synfun_UseSynfun synfun_useSynfun;//組合上面類 public SynThreadText(Synfun_UseSynfun synfun_useSynfun){ this.synfun_useSynfun=synfun_useSynfun;//初始化上面的類 } @Override public void run(){ synfun_useSynfun.fun1();//調用對象類的同步方法 } public static void main(String[] args) { Synfun_UseSynfun synfun_useSynfun =new Synfun_UseSynfun(); SynThreadText synThreadText=new SynThreadText(synfun_useSynfun); synThreadText.start();//開啟線程 } }
結果如下:
總結:可以看出一個線程調用了一個對象的同步方法,那么他也可以調用這個對象的另外一個同步方法。
二.synchronized鎖重入支持父類繼承
那么既然synchronized支持對象的方法重入,那么他是否也支持子類繼承父類的同步方法重入呢?
不妨這樣設計代碼,在父類中有一個同步方法,子類繼承這個方法,並且在創建一個子類的同步方法,在這個同步方法中去調用父類的同步方法。
代碼如下:
public class SubClass extends SuperClass implements Runnable { @Override public void run(){ this.subSynFun(); } //子類的同步方法 public synchronized void subSynFun(){ System.out.println("子類的同步方法"); this.superSynFun(); } public static void main(String[] args) { SubClass sub=new SubClass(); Thread t =new Thread(sub); t.start(); } } //父類 class SuperClass{ //父類的同步方法 public synchronized void superSynFun(){ System.out.println("父類的同步方法"); } }
結果如下:
說明synchronized的方法是可以重入自己的父類同步化方法。
但是在這里要注意一點的:當你去重寫父類中的同步方法,如果想要達到同步的效果重寫方法也必須是同步化的,反面教材代碼如下:
public class SubClass2 extends SuperClass2 implements Runnable{ @Override public void run(){ } //重寫后的方法不為同步的 @Override public void superSynfun(){ System.out.println("子類中重寫了父類中的同步方法,改為非同步"); } } //父類 class SuperClass2{ //父類的同步方法 public synchronized void superSynfun(){ System.out.println("父類的同步方法"); } }
重寫的方法也必須是同步化的才能實現同步。