• 我们首先先看看JMM模型,话不多说,上图:

  • JMM对应的8大原子操作:
read(读取):从主内存读取数据
load(载入):将主内存读取到的数据写入工作内存
use(使用):从工作内存读取数据来计算
assign(赋值):将计算好的值重新赋值到工作内存中
store(存储):将工作内存数据写入主内存
write(写入):将store过去的变量赋值给主内存中的变量
lock(锁定):将主内存变量加锁,标示为线程独占状态
unlock(解锁):将主内存变量解锁,解锁后其他线程可以锁定该变量

  • Sychronized底层对应的JMM模型8大原子操作【lock】和【unlock】
  • 此时即可同时保持
    • 【原子性】:代码成块
    • 【有序性】
    • 【可见性】

感兴趣的同学,可以对代码编译后,看下反编译后的指令,此处我们分析一下:

  • 原理:

    • JVM内置锁通过synchronized使用,通过内部对象Monitor(监视器锁)实现,基于进入与退出Monitor对象实现方法与代码块同步,监视器锁的实现依赖底层操作系统的Mutex Lock(互斥锁)实现,它是一个重量级锁,性能较低。

  • 如果此时存在一个object2,那么当object1对应线程结束后,只唤醒object1对应阻塞队列中的线程:

  • Monitor加锁原理:每个同步对象都有一个自己的Monitor(锁监视器)
    • JVM加锁过程:JVM内置锁,有没有办法能够手动控制加锁与解锁?

  • JDK1.6版本之后对synchronized的实现进行了各种优化,如适应性自旋锁、轻量级锁和偏向锁,并默认开启偏向锁
开启偏向锁:-XX:+UseBiasedLocking -XX:BiasedLockingStartupDelay=

关闭偏向锁:-XX:-UseBiasedLocking

上面详细说了一下重量级锁,如果是轻量级锁,那么就没有对应的【Monitor】监视类,那么轻量级锁是如何进行区分的呢?

  • 来!这里看一下对象结构,不墨迹,撸图:

  • 这里张贴一段jdk源代码(有些深度)
oop.hpp:

class oopDesc {
friend class VMStructs;
private:
volatile markOop _mark;
union _metadata {
Klass* _klass;
narrowKlass _compressed_klass;
} _metadata;
markOop.hpp:
// 32 bits:
// --------
// hash:25 ------------>| age:4 biased_lock:1 lock:2 (normal object) #正常的对象状态
// JavaThread*:23 epoch:2 age:4 biased_lock:1 lock:2 (biased object) #偏向锁的对象状态
// size:32 ------------------------------------------>| (CMS free block)
// PromotedObject*:29 ---------->| promo_bits:3 ----->| (CMS promoted object)
//
// 64 bits:
// --------
// unused:25 hash:31 -->| unused:1 age:4 biased_lock:1 lock:2 (normal object)
// JavaThread*:54 epoch:2 unused:1 age:4 biased_lock:1 lock:2 (biased object)
// PromotedObject*:61 --------------------->| promo_bits:3 ----->| (CMS promoted object)
// size:64 ----------------------------------------------------->| (CMS free block)
  • 这里Mark Word在32位JVM中存储内容为例:

  • 问题又来了,那么JVM内置锁升级优化过程是如何的呢?

  • 偏向锁高效原因:

只需要修改【Object Mark Word】中的【hashcode】标志位为当前线程对应的【Thread ID】;

而如果直接切换到重量级锁,则是一个用户态到内核态的切换。

  • 偏向锁可以被撤销么?

当然可以被撤销,不过要等到当前拥有锁的线程达到安全点,即执行完同步块,才可以撤销。

【Java】【JVM】Sychronized底层加锁原理详解的更多相关文章

  1. Java精通并发-synchronized关键字原理详解

    关于synchronized关键字原理其实在当时JVM的学习[https://www.cnblogs.com/webor2006/p/9595300.html]中已经剖析过了,这里从研究并发专题的角度 ...

  2. 高性能的Redis之对象底层实现原理详解

    对象 在前面的数个章节里, 我们陆续介绍了 Redis 用到的所有主要数据结构, 比如简单动态字符串(SDS).双端链表.字典.压缩列表.整数集合, 等等. Redis 并没有直接使用这些数据结构来实 ...

  3. java环境配置及原理详解

    java环境配置及原理详解 1.java跨平台的本质 我们谈到java,总是提到跨平台这个词.那么java语言是怎么实现跨平台的呢? 我们编写的java代码不是直接让windows系统读取解析,而是在 ...

  4. 通过 JFR 与日志深入探索 JVM - TLAB 原理详解

    全系列目录:通过 JFR 与日志深入探索 JVM - 总览篇 什么是 TLAB? TLAB(Thread Local Allocation Buffer)线程本地分配缓存区,这是一个线程专用的内存分配 ...

  5. 线程池底层原理详解与源码分析(补充部分---ScheduledThreadPoolExecutor类分析)

    [1]前言 本篇幅是对 线程池底层原理详解与源码分析  的补充,默认你已经看完了上一篇对ThreadPoolExecutor类有了足够的了解. [2]ScheduledThreadPoolExecut ...

  6. Spring Aop底层原理详解

    Spring Aop底层原理详解(来源于csdn:https://blog.csdn.net/baomw)

  7. 【转载】JAVA消息服务JMS规范及原理详解

    转载:https://www.cnblogs.com/molao-doing/articles/6557305.html 作者: moyun- 一.简介 JMS即Java消息服务(Java Messa ...

  8. JAVA消息服务JMS规范及原理详解

    JAVA消息服务JMS规范及原理详解 一.简介 JMS即Java消息服务(Java Message Service)应用程序接口,是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应 ...

  9. Java网络编程和NIO详解6:Linux epoll实现原理详解

    Java网络编程和NIO详解6:Linux epoll实现原理详解 本系列文章首发于我的个人博客:https://h2pl.github.io/ 欢迎阅览我的CSDN专栏:Java网络编程和NIO h ...

随机推荐

  1. 再也不用c刷题了!!——c++刷题必备

    致读者: 博主是一名数据科学与大数据专业大二的学生,真正的一个互联网萌新,写博客一方面是为了记录自己的学习历程,一方面是希望能够帮助到很多和自己一样处于困惑的读者.由于水平有限,博客中难免会有一些错误 ...

  2. 15个Nodejs应用场景

    15个Nodejs应用场景 我们已经对Nodejs有了初步的了解,接下来看看Nodejs的应用场景. 2.1 Web开发:Express + EJS + Mongoose/MySQL express  ...

  3. 美国在线CEO:雅虎被Verizon收购或导致裁员

    北京时间9月13日消息,据外媒报道,AOL首席执行官蒂姆·阿姆斯特朗(Tim Armstrong)称,雅虎.AOL和Verizon整合业务,将导致"部分工作岗位的变化". 阿姆斯特 ...

  4. 阿里巴巴年薪800k大数据全栈工程师成长记

    大数据全栈工程师一词,最早出现于Facebook工程师Calos Bueno的一篇文章 - Full Stack (需fanqiang).他把全栈工程师定义为对性能影响有着深入理解的技术通才.自那以后 ...

  5. qemu-img压缩磁盘操作

    2019独角兽企业重金招聘Python工程师标准>>> qemu-img convert -c -f qcow2 -O qcow2 /data/data1.disk /opt/dat ...

  6. Mac查看与修改系统默认shell

    Mac查看与修改系统默认shell 查看所有shell cat /etc/shells 输出: # List of acceptable shells for chpass(1). # Ftpd wi ...

  7. 题目分享V

    题意:现在两个人做游戏,每个人刚开始都是数字1,谁赢了就能乘以k^2,输的乘以k(k可以是任意整数,每次不一定相同)现在给你最终这两个人的得分,让你判断是否有这个可能,有可能的话Yes,否则No. 分 ...

  8. 网上流行护眼色的RGB值和颜色代码

    网上流行护眼色的RGB值和颜色代码   绿豆沙色能有效的减轻长时间用电脑的用眼疲劳!色调:85,饱和度:123,亮度:205: RGB颜色红:199,绿:237,蓝:204:十六进制颜色:#C7EDC ...

  9. NDK clang编译器的一个bug

    NDK clang编译器的一个bug 问题代码 float32_t Sum_float(float32_t *data, const int count) { float32x4_t res = vd ...

  10. 【Spark】Spark-shell案例——standAlone模式下读取HDFS上存放的文件

    目录 可以先用local模式读取一下 步骤 一.先将做测试的数据上传到HDFS 二.开发scala代码 standAlone模式查看HDFS上的文件 步骤 一.退出local模式,重新进入Spark- ...