浅析Synchronized

Synchronized的作用方式:

  • 作用于代码块
  • 作用于实例方法
  • 作用于静态方法
  • 作用于对象

1. 同步代码块和同步实例方法的区别:只有进入同步代码块才会锁住对象,而进入同步方法立即锁住对象。

public void print(){
    System.out.print("进入方法+线程:" + Thread.currentThread.getName());
    Synchronized(obj){
        while(true){}
    }
}

public synchronized void print(){
    System.out.print("进入方法+线程:" + Thread.currentThread.getName());
    while(true){}
}

线程A,B分别同时执行两个print()方法的结果:

进入方法+线程1
进入方法+线程2
===================
进入方法+线程1

2. 同步实例方法锁住对象,同步静态方法和同步类一样锁住class对象

3.JVM内部实现

  对于同步代码块:需要jvm和编译器配合实现。JVM指令集中有monitorenter和monitorexit指令支持synchronized关键字,monitorenter插入到同步代码块开始的地方,monitorexit插入到同步代码块结束的地方,编译器保证每一条monitorenter指令都必须执行对应的monitorexit指令,为了保证方法异常完成时,monitorenter和monitorexit依然正确配对执行,编译器自动产生一个异常处理器,这个异常处理器处理所有异常,目的就是用来执行monitorexit指令。任何对象都有一个monitor与之关联,monitor内部有一个owner字段,初始为null,保存持有该monitor的线程唯一标识。当进入同步时,线程都要尝试获取monitor。

  对于同步方法:无需通过字节码指令控制,实现在方法调用和返回的操作中。JVM从方法常量池的方法表结构中的ACC_SYNCHRONIZED访问标志得知一个方法是否声明为同步方法。当方法调用时,调用指令会检查方法的ACC_SYNCHRONIZED访问标志是否被设置,如果设置了,执行线程就要求先成功持有管程,然后才能执行方法,当方法退出(正常/抛出异常)时,释放管程。   

参考:

https://www.zhihu.com/question/57794716?sort=created

https://www.jianshu.com/p/4e4c67d7ad4a

https://www.jianshu.com/p/d99993b52a07

人生就像蒲公英,看似自由,其实身不由己。
原文地址:https://www.cnblogs.com/walker993/p/9498486.html