一篇搞懂Synchronized所有知识点

119 阅读2分钟

Synhronized底层实现

在代码块中是通过moitorenter和moniterexit等指令实现的,每一个对象都有一个对象监视器(Object Monitor)(指的是锁对象),当对象监视器被占用的时候就会处于锁定状态,执行moitorenter指令时尝试所有权,一般情况下会存在一个moitorenter两个moniterexit,其中两个当中一个是为了在出现异常的情况下,退出锁!

在方法中的实现原理,在理论上是和代码块的实现方式一样的,在同步方法当中是通过ACC_SYNCHRONIZED标识符,当方法调用的时,会检查方法的ACC_SYNCHRONIZED访问标志是否被设置,那么当前线程将获取对象监视器,获取成功后再能访问方法体,执行完之后在释放对象监视器。

具体细节体现

1.当对象监视器进入数为0时,则该线程进入对象监视器,然后将进入数设置为1,此时A线程即为该对象监视器的所有者

2.若A线程已经拥有该对象监视器,当前线程发生重新进入,则该对象监视器的进入数加1

3.若其他线程已经持有了该对象监视器,则当前线程进入阻塞状态,直到对象监视器进入数为0

问题延伸
    关于wait/notify的运行也是需要依赖对象监视器,这就是为什么,只有在同步代码块当中才能使用。

存储结构

image.png

  • Mark word、Klass Pointer属于对象头部分
  • Instance Data属于实例数据部分
  • Padding 对齐填充Padding

Synchronized的特性

  • 原子性 被synchronized保护的代码可以实现原子性

  • 可见性 synchronized保证对共享变量的改变能够及时看见

  • 有序性 根据happen-before 有效解决重排序问题

    • 解释:关于什么是happen-before,系统为了能够高效的的运行在每次运行的时候,都会进行指令的重排序,这就造成了程序执行的顺序改变,进而是程序执行的结果发生改变,通过约束规则使用happen-before能够有效解决重排序问题,比如:A happen-before B 就是A发生于B之前,即A执行结果要对B可见,所以 通过约束规则进而可以解决指令的重排序。*

使用位置

  • 实例方法 锁的对象:类的实例对象,相当于new public synchronized void method(){}
  • 静态方法 锁对象: 类的class对象,唯一对象,表示了该锁的唯一性 锁对象:类的class对象 唯一对象

public static synchronized void method(){}

  • 实例对象 锁对象:类的实例对象 相当于new 指当前类的实例对象 synchronized(this)

  • class对象 锁对象:类的class对象 synchronized(XXX.class){}

  • 任意Object对象 锁对象:实例对象 Test test=new Test(); synchronized(test){}