1.如何证明内置锁sychronized是重入锁

synchronized是Java提供的一种内置锁,它修饰的对象,同一时刻只能被唯一一个锁持有,它可修饰的对象有:

  1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象;
  2. 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;
  3. 修改一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;
  4. 修改一个类,其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象。
从互斥锁的设计原则上来说,当B线程试图操作由A线程
持有的对象锁的临界资源时,B线程将会处于阻塞状态。
但当一个线程再次请求自己持有对象锁的临界资源时,这种情况属于重入。

如下示例, 子类重写父类中的方法doSomeThing(),sayBy(),如果是不可重入的,则会导致死锁。

package com.myConcurrent.demo.mysynchronized;

public class MySynchronizedChild extends MySynchronizedParent {

    @Override
    public synchronized void doSomething() {
        System.out.println("Child say hello");
        super.doSomething();
    }

    public void sayBy() {
        synchronized (this){
            System.out.println("Child say by 01");
            synchronized (this){
                System.out.println("Child say by 02");
            }
        }
    }

    public static void main(String[] args) {
        MySynchronizedChild child = new MySynchronizedChild();
        child.doSomething(); // 01
        child.sayBy(); // 02
    }
}

public abstract class MySynchronizedParent {

    public synchronized void doSomething() {
        System.out.println("Parent say hello");
    }
}

我们通过 javap -verbose 查看 反编译的字节码,关注main 方法的2个地方:
关于01,synchronized对于方法的修饰,采用隐式标记,对方法标记为ACC_SYNCHRONIZED,表示该方法是个内置锁:
关于02,synchronized对于代码块的修饰,采用显示入锁,出锁标志,图中,出现2次 monitorenter 与 monitorexit,均是在同一线程中,重复获取对象锁,再退出对象锁。:


image.png

如上,均证明了synchronized是可重入锁。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容