《白话》 jvm--锁

参考:https://www.cnblogs.com/deltadeblog/p/9559035.html

https://time.geekbang.org/column/article/13530

//www.greatytc.com/p/911c112e0c2f

什么是锁对象??

锁对象就是我们写代码,()里面写的哪个东西。

他存储在java对象头中。


image.png

结构一般如下:


image.png

如果实现?

代码编译后,在字节码层面,增加了monitorenter和monitorexit关键字。

这两个没换一个指令都会消耗操作数栈上的一个引用类型的元素(就是写代码的时候括号里的引用)作为要加锁的对象。

monitorenter和monitorexit的对应关系是一对多。因为monitoredxit不仅要在正常执行路劲,异常执行路劲也需要释放锁。

那么这个锁对象里面,有一个计数器和一个指向持有该锁的线程的指针。

当计数器为0的时候,来一个线程访问,那么就会把指针指向那个线程,然后计数器加1.

在计数器不是0的情况下,如果还是本线程访问,那么计数器加1,如果访问的不是本线程,该线程就等待。

重量级锁(悲观锁)

重量级锁也就是通常说synchronized的对象锁,锁标识位为10,其中指针指向的是monitor对象(也称为管程或监视器锁)的起始地址。每个对象都存在着一个 monitor 与之关联,对象与其 monitor 之间的关系有存在多种实现方式,如monitor可以与对象一起创建销毁或当线程试图获取对象锁时自动生成,但当一个 monitor 被某个线程持有后,它便处于锁定状态。

由此看来,monitor对象存在于每个Java对象的对象头中(存储的指针的指向),synchronized锁便是通过这种方式获取锁的,也是为什么Java中任意对象可以作为锁的原因,同时也是notify/notifyAll/wait等方法存在于顶级对象Object中的原因。

这个情况下,会阻塞和唤醒线程。

对于现在大部分实现了posix接口的操作系统,以上操作,都是通过pthread的互斥量mutex实现的。需要内核态和用户态的切换。消耗比较大。

由于阻塞唤醒的成本比较大,jvm会选择不同的策略。

当根据之前经验判断很快能获得锁,就会进行自旋锁。否则就等待策略。

重量级锁是不公平锁,即无法控制先到先得的顺序。

轻量级锁(乐观锁)

什么情况适合使用轻量级锁??

多个线程在不同的时段请求同意吧锁,也就是没有锁竞争的情况。

什么是mark word??

对象头中有一段,表示mark work,最后两位用来表示锁状态。00表示轻量级锁,01表示无锁(或偏向锁),10表示重量级锁。11跟垃圾回收算法的标记有关。

轻量级锁的实现原理??

加锁过程:

当线程请求一个对象的时候,当jvm判断当前对象头中mark word,是不是重量级锁,如果不是,那么会在当前请求线程的栈帧中开辟一块空间,作为该锁的锁记录,也称作Lock Record(Lock Record中存储的mark word称作displayed mark word),然后将对象头的mark word复制到这个Lock Record中。然后,jvm会利用CAS替换当前锁对象中的mark word(假设当前锁对象的标记字段为 X…XYZ,Java 虚拟机会比较该字段是否为 X…X01。如果是,则替换为刚才分配的锁记录的地址。由于内存对齐的缘故,它的最后两位为 00。此时,该线程已成功获得这把锁,可以继续执行了。如果不是 X…X01,那么有两种可能。第一,该线程重复获取同一把锁。此时,Java 虚拟机重入会在线程栈中分配一个Displaced Mark word为null的Lock Record。第二,其他线程持有该锁。此时,Java 虚拟机会将这把锁膨胀为重量级锁,并且阻塞当前线程。),让他指针指向栈的Lock Record,并且让Lock Record的owner指向锁对象的mark word。

为什么JVM选择在线程栈中添加Displaced Mark word为null的Lock Record来表示重入计数呢?

首先锁重入次数是一定要记录下来的,因为每次解锁都需要对应一次加锁,解锁次数等于加锁次数时,该锁才真正的被释放,也就是在解锁时需要用到说锁重入次数的。一个简单的方案是将锁重入次数记录在对象头的mark word中,但mark word的大小是有限的,已经存放不下该信息了。另一个方案是只创建一个Lock Record并在其中记录重入次数,Hotspot没有这样做的原因我猜是考虑到效率有影响:每次重入获得锁都需要遍历该线程的栈找到对应的Lock Record,然后修改它的值。

所以最终Hotspot选择每次获得锁都添加一个Lock Record来表示锁的重入。

解锁过程:

轻量级锁释放时需要将Displaced Mark Word替换到对象头的mark word中

(你可以将一个线程的所有锁记录想象成一个栈结构,每次加锁压入一条锁记录,解锁弹出一条锁记录,当前锁记录指的便是栈顶的锁记录)

先看当前锁记录的值是不是0,如果是,说明是重复进入同一把锁,直接弹出这个锁记录,如果不是0,Java 虚拟机会尝试用 CAS 操作,比较锁对象的标记字段的值是否为当前锁记录的地址。如果是,则替换为锁记录中的值,也就是锁对象原本的标记字段。此时,该线程已经成功释放这把锁。如果不是,则意味着这把锁已经被膨胀为重量级锁。此时,Java 虚拟机会进入重量级锁的释放过程,唤醒因竞争该锁而被阻塞了的线程。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,372评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,368评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,415评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,157评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,171评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,125评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,028评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,887评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,310评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,533评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,690评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,411评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,004评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,812评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,693评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,577评论 2 353

推荐阅读更多精彩内容