在JDK1.6以前,使用synchronized就只有一种方式即重量级锁,而在JDK1.6以后,引入了偏向锁,轻量级锁,重量级锁,来减少竞争带来的上下文切换。

锁升级主要依赖对象头中的Mark Word中的锁标志位和释放偏向锁标识位。

一般的synchronized同步锁升级步骤是:偏向锁 -> 轻量级锁 -> 重量级锁。

注意:锁只能升级,不能降级。

偏向锁

偏向锁,顾名思义是偏向某一个线程的锁,在该某个线程第一次成功锁时,会在对象头中存储所偏向的线程ID,如果下一次还是该线程获取锁,只需要在对象头Mark Word中去判断一下是否有偏向锁指向它的ID,大大减少了性能的消耗。

什么时候升级为轻量级锁呢?

当有另外一个线程竞争获取这个锁时,由于该锁已经是偏向锁,当发现对象头 Mark Word 中的线程 ID 不是自己的线程 ID,就会进行 CAS 操作获取锁,如果获取成功,直接替换 Mark Word 中的线程 ID 为自己的 ID,该锁会保持偏向锁状态;如果获取锁失败,代表当前锁有一定的竞争,偏向锁将升级为轻量级锁。

轻量级锁

轻量级锁是相对于重量级锁而言,轻量级锁不需要申请互斥量,只需要将Mark Word 中的部分字节CAS更新指向栈中锁记录的指针,如果更新成功,则轻量级锁获取成功,记录锁状态为轻量级锁;否则,说明已经有线程获取了轻量级锁,发生了锁竞争,轻量级锁开始自旋。

自旋锁与自适应自旋锁

自旋锁(包括自适应自旋锁)是轻量级锁在升级为重量级锁前做的最后一次挣扎。

在JDK1.6之前设置自旋锁为自旋超过十次,或者等待线程超过cpu核数的2分之一,锁升级为重量级锁;

在JDK1.6后优化为自适应的自旋锁,如果自旋超过一定次数,或者此时有第三个线程来竞争该锁时,锁升级为重量级锁。

重量级锁

重量级锁是如果多个线程同时竞争锁,只会有一个线程得到这把锁,其他线程获取锁失败,不会和轻量级锁进行自旋等待锁被释放,而是直接阻塞没有获取成功的线程。

重量级锁需要操作系统对线程状态的切换,

当锁升级为重量级锁后,未抢到锁的线程都会被阻塞,进入阻塞队列。

总结

synchronized的执行过程:

  1. 检测Mark Word里面是不是当前线程的ID,如果是,表示当前线程处于偏向锁
  2. 如果不是,则使用CAS将当前线程的ID替换Mard Word中的线程ID,如果成功则表示当前线程获得偏向锁,置偏向标志位1
  3. 如果失败,则说明发生竞争,撤销偏向锁,进而升级为轻量级锁。
  4. 当前线程使用CAS将对象头的Mark Word替换为锁记录指针,如果成功,当前线程获得锁
  5. 如果失败,表示其他线程竞争锁,当前线程便尝试使用自旋来获取锁。
  6. 如果自旋成功则依然处于轻量级状态。
  7. 如果自旋失败,则升级为重量级锁。

synchronized中锁是怎么升级的的更多相关文章

  1. 【转载】Java中的锁机制 synchronized & 偏向锁 & 轻量级锁 & 重量级锁 & 各自优缺点及场景 & AtomicReference

    参考文章: http://blog.csdn.net/chen77716/article/details/6618779 目前在Java中存在两种锁机制:synchronized和Lock,Lock接 ...

  2. java架构之路(多线程)synchronized详解以及锁的膨胀升级过程

    上几次博客,我们把volatile基本都说完了,剩下的还有我们的synchronized,还有我们的AQS,这次博客我来说一下synchronized的使用和原理. synchronized是jvm内 ...

  3. synchronized的锁升级/锁膨胀

    偏向锁 偏向第一个拿到锁的线程. 即第一个拿到锁的线程,锁会在对象头 Mark Word 中通过 CAS 记录该线程 ID,该线程以后每次拿锁时都不需要进行 CAS(指轻量级锁). 如果该线程正在执行 ...

  4. [多线程] 线程中的synchronized关键字锁

    为什么要用锁? 在多线程中,难免会出现在多个线程中对同一个对象的实例变量或者全局静态变量进行并发访问的情况,如果不做正确的同步处理,那么产生的后果就是"脏读",也就是取到的数据其实 ...

  5. Synchronized偏向锁和轻量级锁的升级

    原文:https://blog.csdn.net/tongdanping/article/details/79647337 锁的优化1.锁升级锁的4中状态:无锁状态.偏向锁状态.轻量级锁状态.重量级锁 ...

  6. 并发王者课-青铜7:顺藤摸瓜-如何从synchronized中的锁认识Monitor

    在前面的文章中,我们已经体验过synchronized的用法,并对锁的概念和原理做了简单的介绍.然而,你可能已经察觉到,有一个概念似乎总是和synchronized.锁这两个概念如影相随,很多人也比较 ...

  7. synchronized、锁、多线程同步的原理是咋样

    先综述个结论: 一般说的synchronized用来做多线程同步功能,其实synchronized只是提供多线程互斥,而对象的wait()和notify()方法才提供线程的同步功能. 一般说synch ...

  8. Java-synchronized 中锁的状态及其转换

    synchronized 锁的优化过程:无锁 -> 偏向锁 -> 轻量级锁 -> 重量级锁 一.不同锁对象的状态表示(需要了解 Java 对象头) https://wiki.open ...

  9. synchronized互斥锁实例解析

    目录 synchronized互斥锁实例解析 1.互斥锁基础使用:防止多个线程同时访问对象的synchronized方法. 1.1.多个线程调用同一个方法 1.2.多个线程多个锁,升级为类锁 2.线程 ...

随机推荐

  1. 使用 Nginx 在 Linux 上托管 ASP.NET Core

    server { listen 80; server_name example.com *.example.com; location / { proxy_pass http://localhost: ...

  2. GitHub Actions 支持 "skip ci" 了

    GitHub Actions 支持 "skip ci" 了 Intro GitHub Actions 作为 GitHub 官方的 CI 支持,很多开源项目已经在使用 Actions ...

  3. Node.js 返回 JSON 数据

    Node.js 返回 JSON 数据 request.end([data[, encoding]][, callback]) var http = require('http'); const log ...

  4. 微软收购 GitHub

    微软收购 GitHub 微软收购 GitHub震惊业界:引发开发者信任问题 https://news.cnblogs.com/n/598432/ GitLab refs xgqfrms 2012-20 ...

  5. TweenMax & GSAP & SVG Animation

    TweenMax & GSAP & SVG Animation svg animation https://greensock.com/tweenmax GSAP https://ww ...

  6. flutter practical

    flutter practical https://flutterchina.club/ https://github.com/flutterchina/flutter-in-action https ...

  7. CSS3 & CSS var & :root

    CSS3 & CSS var & :root How to change CSS :root color variables in JavaScript https://stackov ...

  8. select notes mark

    select notes mark mark-line https://time.geekbang.org/column/article/224545

  9. js 动态构建style

    使用创建style的方式 btn.addEventListener("click", async () => { const ns = document.createElem ...

  10. JsBridge & Android WebView

    JsBridge & Android WebView webview loadUrl addJavascriptInterface .setJavaScriptEnabled(true); f ...