疯狂java


您现在的位置: 疯狂软件 >> 新闻资讯 >> 正文

java线程之synchronized的注意细节


 

  

  我在学习synchronized的时候,十分好奇当一个线程进入了一个对象的一个synchronized普通方法后,其它线程是否可进入此对象的其它方法?

  然后就做了个实验(实验代码最后贴出),最后得到了如下结论:

  1)其它方法是加了synchronized的普通方法,不能;

  2)其它方法是没加synchronized的普通方法,能;

  3)其它方法是synchronized的static方法,能;

  4)其它方法是没加synchronized的static方法,能。

  当一个线程进入了一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法:

  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.