• 我们首先先看看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. Netty(二):数据在ChannelPipeline中的流经

    本文目的:测试数据在ChannelPipeline中的流经顺序及状态. 先看本文的测试代码: AdditionalInBoundHandler:入站处理器,不做任何处理,只是在响应读事件时打印用来观察 ...

  2. SaaS 公司如何切入大客户

    编者按:本文作者是氪空间第四期项目 Kuick 创始人崔超,其现在的产品KuickDeal是一款销售活动管理工具.本文来自作者投稿,36 氪经授权转载. 首先,今天我们不讨论 SaaS 公司应该做中小 ...

  3. Lucene的FuzzyQuery中用到的Levenshtein Distance(LD)算法

    2019独角兽企业重金招聘Python工程师标准>>> Lucene的FuzzyQuery中用到的Levenshtein Distance(LD)算法 博客分类: java 搜索引擎 ...

  4. 第 38 章 OCR - Optical Character Recognition

    38.1. Tesseract 查找Tesseract安装包 $ apt-cache search Tesseract ocrodjvu - tool to perform OCR on DjVu d ...

  5. 写给MongoDB开发者的50条建议Tip21

    本系列文章翻译自<50 Tips and Tricks for MongoDB Developers>,暂时没有找到中文版,反正自己最近也在深入学习mongodb,所以正好拿来翻译一下.一 ...

  6. Centos7网络配置( 网关、dns、ip地址配置)

    0.前提:设置VMware的虚拟网络编辑器 子网和网关设置   虚拟网络编辑器 1.配置DNS(可忽略) $vim /etc/resolv.conf nameserver 192.168.0.1 2. ...

  7. centos6.5宽带拨号上网

    CentOS6以后要安装rp-pppoe这个软件,centos之前的版本是adsl-setup命令安装. (1)查看是否安装 #rpm -qa|grep rp-pppoe 没有内容输出则没安装,若可以 ...

  8. P1466 集合 Subset Sums 搜索+递推+背包三种做法

    题目描述 对于从1到N (1 <= N <= 39) 的连续整数集合,能划分成两个子集合,且保证每个集合的数字和是相等的.举个例子,如果N=3,对于{1,2,3}能划分成两个子集合,每个子 ...

  9. Python基础00 教程

    Python: 简明 Python 教程 廖雪峰Python3教程 Python快速教程 (手册) 爬虫: 汪海的实验室:Python爬虫入门教程 静觅: Python爬虫学习系列教程 Flask: ...

  10. python学习之break和continue在for循环中的使用(案例:打印出10以内的偶数,并且只要前三个偶数)

    运行程序,break是整个程序都跳出 continue则表示跳过当前一次循环,然后继续执行循环