1、synchronized 关键字的锁对象是谁?

①当synchronized 关键字加在实例方法上,那么锁对象是当前类实例

示例代码

synchronized void a() {
    try {
        Thread.sleep(3000L);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println("a");
}

synchronized void b() {
    System.out.println("b");
}

public static void main(String[] args) {
    ThreadTest test = new ThreadTest();
    new Thread(() -> {
        test.b();
    }).start();

    new Thread(() -> {
        test.a();
    }).start();
}

②、当synchronized 关键字加在静态方法上,那么锁对象是当前类

示例代码

static synchronized void a() {
     System.out.println("aaaa");
    try {
        Thread.sleep(3000L);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println("a");
}

static synchronized void b() {
    System.out.println("b");
}

public static void main(String[] args) {
    ThreadTest test = new ThreadTest();
    ThreadTest test1 = new ThreadTest();
    new Thread(() -> {
        ThreadTest.a();
    }).start();

    new Thread(() -> {
        ThreadTest.b();
    }).start();
}

2、synchronized 关键字可重入吗?

synchronized 是可重入的!

示例代码

synchronized void a() {
    System.out.println("aaaa");
    b();
    try {
        Thread.sleep(3000L);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println("a");
}

synchronized void b() {
    System.out.println("b");
}

public static void main(String[] args) {
    ThreadTest test = new ThreadTest();
    test.a();
}

a方法中调用b方法。因为当前的锁对象是类的实例,调用a方法时,可以立马调用b方法,说明sychronized是可重入的。

3、synchronized是如何加锁的?

①从字节码层面看

image

Jvm 生了2个字节码命令

monitorenter代表进入

monitorexit代表退出

②从jvm层面看

问题一:synchronized的锁信息存放在哪里?

synchronized 的锁信息存放在对象头中。

对象头中包含2个部分

1、MarkDown

2、示例数据(存放对象的字段内容)

MarkDown 中包含了锁的标记位。

其中锁有偏向锁,轻量级锁,重量级锁。

3者的使用场景如下:1个线程进入临界区,多个线程交替进入临界区,多个线程同时进入临界区

偏向锁
只有1个线程进入临界区,线程获取锁之后,不会释放锁,再次进入的时候无需再次加锁

轻量级锁
多个线程交替进入临界区,以自旋的方式进行忙循环。线程不会被挂起。也就是线程不会被切换出去。

重量级锁
线程会被挂起,会被切换出去。


心无私天地宽
513 声望22 粉丝