关于java线程锁synchronized修饰普通方法与静态方法的区别

时间:2021-08-06 11:32:24

最近研究线程方面问题,关于这个synchronized锁修饰的问题,先是修饰普通方法,然后通过两个线程,各自执行自己对象的锁,发现方法执行互不影响,代码如下:

  private static int num=0;
  private synchronized void printNum(String tag){
    try {
    if(tag.equals("a")){
      num=100;
      System.out.println("tag a,num set over!");
      Thread.sleep(1000);//休眠1秒
    }else{
      num=200;
      System.out.println("tag b,set num over!");
    }
  } catch (InterruptedException e) {
    e.printStackTrace();
  }
  System.out.println("tag :" +tag+", num="+num);
  }
  public static void main(String[] args) {
    MyThread02 my1=new MyThread02();
    MyThread02 my2=new MyThread02();
    //匿名内部类方式启动线程
    new Thread(()->my1.printNum("a")).start();
    new Thread(()->my2.printNum("b")).start();
  },

执行结果如下,即可能一个线程刚设置完num,另一个线程来再来设置num,两个线程两个锁没有任何影响.

tag a,num set over!
tag b,set num over!
tag :b, num=200
tag :a, num=200

但是如果修饰的是静态方法,发现打印顺序就是一致的,也就是说此时这个方法同时只能一个线程执行,结果不变如下:

tag a,num set over!
tag :a, num=100
tag b,set num over!
tag :b, num=200

后面百度了解到,在多个线程多个锁的情况下,

如果synchronized修饰在普通方法上,线程之间互无关系,可任意执行自己对象的锁
如果在static方法上修饰synchronized表示锁定了class类.多个线程都是相同的一把锁,即
取得的锁都是对象锁,哪个线程先执行代码,哪个线程就持有该方法所属的对象锁,其他对象就无法执行