我在學習synchronized的時候,十分好奇當一個線程進入了一個對象的一個synchronized方法後,其它線程是否可進入此對象的其它方法?java
而後就作了個實驗(實驗代碼最後貼出),最後獲得了以下結論。ide
如今分兩種狀況來討論:1.當前線程調用的是synchronized普通方法(相對於static方法);2.當前線程調用的是synchronized static方法。學習
1.當前線程調用的是synchronized普通方法(相對於static方法)時,其它線程是否可進入此對象的其它方法:測試
1)其它方法是加了synchronized的普通方法,不能;this
2)其它方法是沒加synchronized的普通方法,能;spa
3)其它方法是synchronized的static方法,能;線程
4)其它方法是沒加synchronized的static方法,能。對象
2.當前線程調用的是synchronized static方法,其它線程是否可進入此對象的其它方法:blog
1)其它方法是加了synchronized的普通方法,能;同步
2)其它方法是沒加synchronized的普通方法,能;
3)其它方法是synchronized的static方法,不能;
4)其它方法中有synchronized(xxx.class)的,不能;
5)其它方法是沒加synchronized的static方法,能。
其實只要明白了普通方法加synchronized的本質是給對象的this加了對象鎖,上面的結論就不難理解了,
其中無論static方法是否加synchroized,只要鎖的是this,即當前對象,而不是當前類(XXX.class),就能夠執行;
而給當前類加鎖時,除了同步的static方法不能調用外,其它的均可以。
實驗代碼以下:
package javaBase; public class JB_052_Synchronized { public static void main(String[] args) { Resource_052 rs = new Resource_052(); Thread t1 = new Thread(new Thread1_052(rs)); //調用synchronized方法的線程 Thread t0 = new Thread(new Thread0_052(rs)); //調用普通方法的線程 Thread t2 = new Thread(new Thread2_052(rs)); //調用另外一個synchronized方法的線程 Thread t3 = new Thread(new Thread3_052(rs)); //調用synchronized static 方法的線程 Thread t4 = new Thread(new Thread4_052(rs)); //調用static方法的線程 Thread t5 = new Thread(new Thread5_052(rs)); //調用鎖class方法的線程 t1.start(); //調用了synchronized方法 try{ System.out.println("調用synchronized方法的thread1啓動後主程序等待2秒,確保在其它線程執行以前thread1得到對象鎖"); Thread.sleep(2000); }catch(InterruptedException e){ e.printStackTrace(); } t0.start(); //調用了普通方法 //能夠 t2.start(); //調用了另外一個synchronized方法 //不行 t3.start(); //調用了synchronized static 方法 //能夠 t4.start(); //調用了static方法 //能夠 //鎖class try{ System.out.println("主程序等待10秒,等前面的線程除thread1和被阻塞的線程外都執行完成,後面的代碼將作鎖class測試...."); Thread.sleep(10000); System.out.println("10秒等待完。"); }catch(InterruptedException e){ e.printStackTrace(); } //thread5中會置flag=false終止thread1 t5.start(); try{ System.out.println("主程序等待10秒,確保thread5得到class的對象鎖,確保thread1和被阻塞的線程都終止。"); Thread.sleep(10000); System.out.println("10秒等待完。"); }catch(InterruptedException e){ e.printStackTrace(); } t0 = new Thread(new Thread0_052(rs)); //普通方法 t2 = new Thread(new Thread2_052(rs)); //另外一個synchronized方法 t3 = new Thread(new Thread3_052(rs)); //synchronized static 方法 t4 = new Thread(new Thread4_052(rs)); //static方法 t0.start(); //調用了普通方法 //能夠 t2.start(); //調用了另外一個synchronized方法 //不行 t3.start(); //調用了synchronized static 方法 //不能夠 t4.start(); //調用了static方法 //能夠 } } class Resource_052{ public boolean flag = true; public void method0(){ System.out.println("this is a ordinary method——method0."); } synchronized public void method1(){ while(flag){ System.out.println("this is a synchronized method——method1."); try{ Thread.sleep(2000); }catch(InterruptedException e){ e.printStackTrace(); } } } synchronized public void method2(){ System.out.println("this is the second synchronized method——method2."); } synchronized public static void method3(){ System.out.println("this is a synchronized static method——method3."); } public static void method4(){ System.out.println("this is a ordinary static method——method4."); } public void method5(){ synchronized(Resource_052.class){ while(true){ System.out.println("this is a synchronized static method——method5."); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } } } synchronized public static void method6(){ //與method5等價 while(true){ System.out.println("this is a synchronized static method——method6."); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } } } class Thread1_052 implements Runnable{ private Resource_052 rs; /** * constructor * @param rs */ public Thread1_052(Resource_052 rs){ this.rs = rs; } @Override public void run(){ this.rs.method1(); //調用synchronized方法 } } class Thread0_052 implements Runnable{ private Resource_052 rs; /** * constructor * @param rs */ public Thread0_052(Resource_052 rs){ this.rs = rs; } @Override public void run(){ this.rs.method0(); //調用普通方法 } } class Thread2_052 implements Runnable{ private Resource_052 rs; /** * constructor * @param rs */ public Thread2_052(Resource_052 rs){ this.rs = rs; } @Override public void run(){ this.rs.method2(); //調用另外一個synchronized方法 } } class Thread3_052 implements Runnable{ private Resource_052 rs; /** * constructor * @param rs */ public Thread3_052(Resource_052 rs){ this.rs = rs; } @Override public void run(){ this.rs.method3(); //調用synchronized static方法 } } class Thread4_052 implements Runnable{ private Resource_052 rs; /** * constructor * @param rs */ public Thread4_052(Resource_052 rs){ this.rs = rs; } @Override public void run(){ this.rs.method4(); //調用普通static方法 } } class Thread5_052 implements Runnable{ private Resource_052 rs; /** * constructor * @param rs */ public Thread5_052(Resource_052 rs){ this.rs = rs; } @Override public void run(){ rs.flag=false; this.rs.method5(); //調用鎖Class的方法 try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } }
獲得的結果以下:
==================================================================================================
調用synchronized方法的thread1啓動後主程序等待2秒,確保在其它線程執行以前thread1得到對象鎖
this is a synchronized method——method1.
this is a synchronized method——method1.
主程序等待10秒,等前面的線程除thread1和被阻塞的線程外都執行完成,後面的代碼將作鎖class測試....
this is a ordinary method——method0.
this is a synchronized static method——method3.
this is a ordinary static method——method4. //從這裏的結果能夠看到synchronized 普通方法method3沒有執行
this is a synchronized method——method1.
this is a synchronized method——method1.
this is a synchronized method——method1.
this is a synchronized method——method1.
10秒等待完。
主程序等待10秒,確保thread5得到class的對象鎖,確保thread1和被阻塞的線程都終止。
this is a synchronized static method——method5.
this is the second synchronized method——method2.
this is a synchronized static method——method5.
this is a synchronized static method——method5.
this is a synchronized static method——method5.
this is a synchronized static method——method5.
10秒等待完。
this is a ordinary method——method0.
this is a ordinary static method——method4.
this is the second synchronized method——method2. //能夠看到synchronized static方法method3沒有執行
this is a synchronized static method——method5.
this is a synchronized static method——method5.
this is a synchronized static method——method5.
this is a synchronized static method——method5.
this is a synchronized static method——method5.
==================================================================================================