侧边栏壁纸
博主头像
再见理想博主等级

只争朝夕,不负韶华

  • 累计撰写 112 篇文章
  • 累计创建 64 个标签
  • 累计收到 4 条评论

目 录CONTENT

文章目录

Synchronized 四种使用方式

再见理想
2022-05-25 / 0 评论 / 0 点赞 / 285 阅读 / 1,129 字

Synchronized 四种使用方式

public class Demo {

    public synchronized static void a(){
        //TODO
    }
    public synchronized void b(){
        //TODO
    }
    public static void c(){
        synchronized (Demo.class){
            //TODO
        }
    }
    public void d(){
        synchronized (this){
            //TODO
        }
    }
}

a 方法,考察对 static 关键字的理解

 public synchronized static void a(){
        //TODO
    }

static 方法一般称为静态方法,又叫类方法。从名字就可以知道,它是隶属于一个类的。因此调用 static 方法的时候直接使用类名就可以。static 方法不依附于任何对象而存在。this 指向当前对象,因此是不可以使用 this 来调用的。也正是由于这个特性,我们在 static 方法中不能访问类的非静态变量和非静态方法,因为类的非静态变量和非静态方法是依附于对象而存在的。

b 方法,考察对 synchronized 关键字的理解

public synchronized void b(){
        //TODO
    }

用 synchronized 关键字修饰的方法叫同步方法,它是用来做同步操作的。很多面试者认为 synchronized 锁定的是代码块,其实不然。它锁定的是调用当前方法的对象。

比如,多个线程同时执行 demo 对象的 b 方法时:

线程 t1 执行 demo.b()
线程 t2 执行 demo.b()

实际上,t1 和 t2 两个线程需要去竞争 demo 对象的锁,谁竞争到锁,谁就先执行,而另一个则后执行。demo 对象的锁是不容易被编程者感知的。但作为一个合格的程序员,你要知道这背后的机制。

在 Java 中,Jvm 会为每个对象内置一个监视器(monitor),监视器中有一个地方叫监视区域,任何线程要想执行这个对象的 synchronized 方法,都必须先进入到该对象的监视区域。监视器负责保证同一时刻只有一个线程在监视区域执行。

正是由于监视器机制的存在,synchronized 才得以发挥其作为同步关键字的作用。

c 方法,考察对 Class 元类的理解

public static void c(){
        synchronized (Demo.class){
            //TODO
        }
    }

从Jvm的角度来看,在Java中,任何一个对象都能找到其所属的类。Jvm 会为每个类都维护唯一的一个 Class 类对象,用于记录这个类的原始信息,这也是 Java 中反射机制能够存在的底层基础。

如果你了解这个机制,你就可以理解 c 方法中的 synchronized 代码块的作用。它是给 Demo 类对应的 Class 对象加锁的,即多个线程会竞争以进入 Demo.class 这个对象的监视器区域。

如果你还是不理解 Demo.class 对象,让我们来看下面的几行代码:

Demo demo=new Demo();
System.out.println(Demo.class);
System.out.println(demo.getClass());

运行它,你会发现,Demo.class 和 demo.getClass() 是一样的。没错,它们指向同一个内存空间。确切的说,是同一个对象。对于getClass() 方法,它隶属于 Object 类,Jdk文档是这么介绍它的:

Returns the runtime class of this Object. The returned Class object is the object that is locked by static synchronized methods of the represented class.

这段解释是非常精辟了,从中我们也获得了一个额外信息,那就是用 static synchronized 修饰的 a 方法也是锁定的 Demo.class 对象,所以,c方法和a方法是等价的。

如果你在面试中得出这样的结论,不用怀疑,我会对你刮目相看的。

d 方法,考察对 this 关键字的理解

public void d(){
        synchronized (this){
            //TODO
        }
    }

如果用一句话来概括:this 指的是调用当前方法的对象。因此,哪个对象的 d 方法被线程调用,就锁定哪个对象。比如在下面的代码:

Demo demo1=new Demo();
demo1.d();// 第一次调用
Demo demo2=new Demo();
demo2.d();// 第二次调用

第一次调用时,synchronized(this) 中的 this 指定的 demo1 对象,因此锁定的是 demo1 对象。第二次调用时,synchronized(this) 中的 this指定的 demo2 对象,因此锁定的是 demo2 对象。

在前面的讲解中,b 方法也是锁定调用当前方法的对象。因此,b方法和d方式是等价的。

0

评论区