java线程之——synchronized的注意细节
我在学习synchronized的时候,十分好奇当一个线程进入了一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法?
然后就做了个实验(实验代码最后贴出),最后得到了如下结论。
现在分两种情况来讨论:1.当前线程调用的是synchronized普通方法(相对于static方法);2.当前线程调用的是synchronized static方法。
1.当前线程调用的是synchronized普通方法(相对于static方法)时,其它线程是否可进入此对象的其它方法:
1)其它方法是加了synchronized的普通方法,不能;
2)其它方法是没加synchronized的普通方法,能;
3)其它方法是synchronized的static方法,能;
4)其它方法是没加synchronized的static方法,能。
2.当前线程调用的是synchronized static方法,其它线程是否可进入此对象的其它方法:
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.
==================================================================================================