java中的类锁与对象锁

在java中使用synchronized进行同步,锁的类型有类锁与对象锁之分。

一、对象锁

 当多个线程操作同一个实例的时候才产生作用。 

1、修饰代码块

   使用this:属于对象锁

public void do() {
    synchronized (this) {  //  this:属于对象锁 与public synchronized void doVoid() { } 同步
        System.out.println("is base");
    }

2、修饰方法

这种直接修饰在方法是咱个情况?其实和修饰代码块类似,只不过此时默认使用的是this,也就是当前对象的锁。这样写起代码来倒也比较简单明确。与第一点修饰代码块的区别主要还是控制粒度的区别。

public synchronized void doVoid() { }    //对象锁 与synchronized (this){} 同步

 多线程同时执行上述两种方法是需要同步的,获取对象锁才能执行。

二、类锁

当多个线程操作不同的实例,但是这些实例同属于一个类时候产生作用。

1、修饰静态方法

 private static synchronized void method1(){   //类锁
       //与synchronized (BaseClass.class){} 同步
  }

静态方法难道有啥不一样吗?确实是不一样的,此时获取的锁已经不是this了,而this对象指向的class,也就是类锁。因为Java中的类信息会加载到方法常量区,全局是唯一的。这其实就提供了一种全局的锁。

2、使用xxx.class

 public  static void doStaticVoid() {
          synchronized (BaseClass.class) {  //类锁,此方法执行,则与private static synchronized void method1()方法同步
            //这种情况其实和修改静态方法时比较类似,只不过还是一个道理这种方式可以提供更灵活的控制粒度。
          }
      }    
  }

多线程同时执行上述两种方法是需要同步的,获取类锁才能执行。

三、总结

 何时产生同步?

       假如我们有两个 Student类的实例stu1、stu2。

      Student类中的方法如下:

class Student{

   //对象锁
   public void fun1() {
    synchronized (this) { 
        .....
    }

   //对象锁
   public synchronized void fun2() { 

        .....
   } 
   
   //类锁
   public void fun3() {
    synchronized (Student.class) { 
        .....
    }

   //类锁
   public synchronized void fun4() { 

        .....
   } 
}

1、  线程A操作stu1中的对象锁方法即fun1或者fun2,线程B操作stu2中的对象锁方法即fun1或者fun2,则A、B线程不会产生同步,一个获取stu1的对象锁,一个获取stu2的对象锁,何来同步呢?

       若A、B两线程同时操作stu1中的对象锁方法即fun1或者fun2,则会产生同步。

2、 线程A操作stu1中的类锁方法即fun3或者fun4,线程B操作stu2中的类锁方法即fun3或者fun4,则A、B线程产生同步,两线程获取的是一个锁,即 Student类锁。

猜你喜欢

转载自blog.csdn.net/qq_40259907/article/details/82837512