并发编程(二) -- synchronized

一:摘要概述

  • synchronized应用
  • synchronized实现
  • 偏向锁状态
  • 轻量级锁与重锁

二:synchronized应用

场景 加锁对象
静态方法 类Class对象
实例方法 this对象
代码块 括号内对象

三:synchronized实现

一切皆对象的Java中synchronized也是用对象实现的锁,JVM中对象分为对象头实例数据对齐填充,synchronized锁就存在与对象头中

对象头中有一块区域称之为Mark Word,里面存储对象自身的一些运行时数据。包括hash值、GC年龄、锁状态标志等,Mark Down随着锁状态变化如下:

synchronized同步代码块实现就是通过两个命令monitorentermonitorexit,方法同步也是采用类似原理。两个命令必须成对出现 写一个如下简单demo后进入class字节码所在文件目录执行命令javap -v SynchronizedTest.class反编译

public class SynchronizedTest {
    
    private static final Object LOCK = new Object();
    
    public static void main (String[] args) {
       synchronized (LOCK){
           System.out.println(123);
       }
    }
}
复制代码

有两个monitorexit并不奇怪,还有一个是在异常发生时执行。也就是synchronized代码块中发生异常会自动释放锁

四:偏向锁状态

synchronized经过JDK1.6的优化过后引入了偏向锁与轻量级锁,完整的synchronized加锁状态分为:无锁偏向锁轻量级锁重量级锁

4.1 偏向锁加锁

4.2 偏向锁释放

偏向锁的释放是在出现锁竞争时进行释放,当线程争抢锁资源时会暂停所有线程并取消偏向锁膨胀为轻量级锁

五:轻量级锁与重量级锁

轻量级锁的实现其实就是在执行同步代码块之前,JVM会会在当前线程的栈帧中创建锁记录空间,并且将Mark Work 区域内容复制到锁记录空间中。然后使用CAS尝试获取锁,成功则将Mark Work区域指针指向锁记录空间,失败则使用CAS自旋获取锁

轻量级锁的释放就是在自旋获取锁失败时,这时候锁就会膨胀为重量级锁。所有未获取锁线程进入等待状态。锁的优缺点对比如下图:

最后主要阐述一点:锁的整个膨胀过程不可逆

猜你喜欢

转载自juejin.im/post/5eec521a6fb9a0586705f802