synchronized底层原理

共 1834字,需浏览 4分钟

 ·

2021-05-28 10:59

点击上方蓝色字体,选择“标星公众号”

优质文章,第一时间送达

  作者 |  zwy2021 

来源 |  urlify.cn/UZFj6b

76套java从入门到精通实战课程分享

通过反编译class文件,可以看到synchronized最关键的部分是monitor对象。

又因为synchronized关键字使用的方法不同,可以将monitor对象使用分为以下两种情况。

  • synchronized放在方法签名上


    public synchronized void method(){
        
    }

这时候在反编译文件里,该方法的ACC_SYNCHRONIZED访问标志位会被标记

  • synchronized作为对象锁

    public void method(){
      synchronized(new Object()){
       
      }
    }

这时候ACC_SYNCHRONIZED并不会被标记,但是会执行monitorenter和monitorexit命令,从而实现同步。

  • 可以看到虽然只有一个monitorenter但是有两个monitorexit,这是因为有两种情况可以让当前线程放弃锁,即

    • 当前synchronized代码块运行完

    • 发生中断

monitor对象

其实以上两种方法都是相同的,ACC_SYNCHRONIZED标志位是隐式调用了monitor对象而已。下面来说一下monitor对象以及它是如何实现运作的。

monitor的数据结构

关于存储的monitor对象有以下三种可能,对应不同的synchronzied使用方式,

  • synchronzied修饰普通方法——>锁的是this,也就是调用当前方法的实例对象

  • synchronized修饰代码块——>锁的是synchronized后面括号里的方法

  • synchronized修饰static方法——>锁的是类的.class对象

    关于面试的时候会问的各种情况下会不会同步执行,牢记一点

    锁的对象相同才会同步执行

    锁的对象相同才会同步执行

    锁的对象相同才会同步执行

    也就是说,类锁对普通方法锁是不存在覆盖的,下面两个方法不会同步执行

    public synchronized void method1(){
            
        }
        public  static synchronized void method2(){
            
        }

monitor运行机制

如果一个线程运行到一个同步代码块,如果线程进入数为0,则该线程可拥有此monitor对象的锁,遇到monitorenter,进入数+1,遇到monitorexit,进入数-1。

如果目前线程进入数不为0,则当前线程不能获得此monitor对象的锁,需要等待。

synchronized的可重入性,不可中断性是如何保障的呢?

monitor对象的线程进入数不是0和1,如果发生重入,进入数+1即可。

不可中断性:一个线程获取锁后,其他线程必须阻塞或等待,不能抢占,按照上面的运行机制,必须线程进入数=0其他线程才能获得锁,因而,不可中断性实现。

另外,有的面试题会问非同步方法和同步方法同时调用会不会同步执行,答案是不会。

因为,非同步方法执行时不会去考虑线程进入数以及获得锁一系列流程,直接开始执行,怎么可能同步执行呢







浏览 33
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报