博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Synchronized 锁升级
阅读量:3576 次
发布时间:2019-05-20

本文共 942 字,大约阅读时间需要 3 分钟。

Synchronized是JAVA锁的一种形式,是基于JVM层面进行实现。主要有两种用法

  • 修饰方法
    • 在实现时,class文件有特殊标识符ACC_SYNCHRONIZED作用于同步方法
  • 修饰代码块
    • 在实现时,class文件会有两条指令monitorenter及monitorexit,作用于代码块之间

在jdk6之后Synchrozied 升级了,具有多种锁的形式,偏向锁,轻量级锁,自旋锁,及重量级锁。这几种锁之间是只升不降。

即偏向锁可以升级为轻量级锁,但是轻量级锁不能降低为偏向锁。接下来我们来看看锁是怎么升级的。

首先来看看一个作用于Synchronized对象是怎么表示"被获得锁的",主要是用对象头的32个字节来标识的。接下来我们借用一张图,来看看对象头。

当锁处于不同时期的时候,这32个字节所存在的内容也是不一样的。

当一个线程要获得锁的时候,是从偏向锁开始的。首先判断该对象头是否处于无锁状态或者偏向锁状态,如果是则利用CAS操作将对象头的线程ID替换为当前ID,如果CAS操作成功,则代表获得偏向锁。如果失败则证明当前偏向锁被其他线程获得,需要注意的是偏向锁并不会主动释放,所以我们先看看获得该锁的线程是否存活,如果死了,就想锁置为无锁状态或者指向当前线程,如果线程存活,我们就去该线程的栈中看看锁记录是否还需要占用当前锁(这一步是我认为的),如果不占用,那还是置为无锁状态或者指向当前线程。如果占用,jvm 会再安全点释放偏向锁,并升级为轻量级锁。

当线程获得轻量级锁时,首先会将对象头的markword字段复制到本线程的栈帧的锁记录空间中,并利用cas操作将原markword改为锁记录空间的指针,当线程2通过cas操作失败时,则先自旋一段时间。若通过多次自旋依然失败,则锁升级为重量级锁。

至于重量级锁,我觉得就是类似于AQS的双向队列,有一个监视器,他有一个队列,保存需要该锁的线程。

从偏向锁,轻量级锁,自选旋,到重量级锁。其实是锁不断升级优化的过程。偏向锁适用于大部份时间只有一个线程的场景,其消耗最小。

有一点题外话记录一下:synchronized是确保了在获取锁和释放锁的时候都有内存屏障,且数据一定会从主内存中重新load或者store到主内存。

转载地址:http://chagj.baihongyu.com/

你可能感兴趣的文章
eclipse安装maven和简单使用
查看>>
关于交往所思
查看>>
jdbc的封装
查看>>
数据库存入数据变为???
查看>>
实现数据库源的几种方式和开源数据源的使用
查看>>
元数据的获取和 数据库读写操作封装
查看>>
java文件的上传和下载(细节问题)
查看>>
DBUtils框架QueryRunner的 使用
查看>>
springMVC之controller笔记
查看>>
springmvc类型转换
查看>>
ai 的研究生院校
查看>>
spring开发步骤以及bean的配置和注入方式
查看>>
关于鼻炎的日常饮食和注意
查看>>
Spring的IOC的注解的详解
查看>>
成长吧
查看>>
莫名火了
查看>>
宽字节注入
查看>>
渗透测试学习笔记
查看>>
burp 使用
查看>>
spring中IOP的配置
查看>>