Java中的锁系列2

经常听到人家说什么偏向锁、轻量级锁、重量级锁、自旋锁,自适应自旋锁。每当这个时候,以前的我是一脸懵逼…


那到底什么是偏向锁、轻量级锁、自旋锁和重量级锁?

首先我们需要明确一个概念,所有的这些锁都是针对JVM的内容对象锁。是synchronized实现里相关的东西。所以,要了解这些锁,我们必须要知道synchronized在JVM里的实现原理。

JVM基于进入和退出Monitor对象来实现synchronized。在synchronized代码块开始位置织入monitorenter,在结束的位置(正常结束和异常结束处)织入monitorexit指令。线程执行到monitorenter处,会获取锁对象锁对应的monitor的所有权,即尝试获得对象的锁。(任意对象都有一个monitor与之关联,当且一个monitor被持有后,他处于锁定状态)。

一、对象里存了什么东西

既然是对象锁,那我肯定要知道对象是啥。

那java的对象结构到底是什么样子的呢?我们看下Hotspot JVM中,32位机器下,对象的存储内容。


这个图一定要仔细看下。我们有时候也把第一个32位也叫MarkWord。

比如一个Integer对象,实际大小是:4(MarkWord)+4(对象地址)+4(实际int值)+4(补全的对齐)。所以,下次人家问一个Integer占多少字节的时候,勇敢的说出来:16个字节,int的4倍。


二、锁的状态和升级

从上面的图中的MarkWord,我们可以知道一个对象有4种锁的状态,由低到高依次为:无锁状态。偏向锁、轻量级锁、重量级锁,其实这些都是锁的状态。并且JVM还规定锁的等级只可以升级,不可以降级。这种锁升级却不能降级的策略,目的是为了提高获得锁和释放锁的效率。


三、偏向锁

首先为什么要有偏向锁?

偏向锁是为了在无锁竞争的情况下,避免在轻量级锁获取过程中执行不必要的CAS原子指令,因为CAS原子指令虽然相对于重量级锁来说开销比较小但还是存在非常可观的本地延迟。

那偏向锁是怎么做到减少CAS的原子指令的呢?

我们来看下偏向锁的获取和释放流程:

1、线程A获得锁,会在线程A的的栈帧里创建lock record(锁记录变量),则在锁对象的对象头里和lock record里存储线程A的线程id.以后该线程的进入,就不需要CAS操作,只需要判断是否是当前线程。

2、线程A获取锁后,不会主动释放锁。直到线程B也要竞争该锁时,线程A才会释放锁。

偏向锁的释放,需要等待全局安全点(在这个时间点上没有正在执行的字节码),它会首先暂停拥有偏向锁的线程,然后检查持有偏向锁的线程是否还活着,如果线程不处于活动状态,则将对象头设置成无锁状态。如果线程仍然活着,拥有偏向锁的栈会被执行,遍历偏向对象的所记录。栈帧中的锁记录和对象头的Mark Word要么重新偏向其他线程,要么恢复到无锁,或者标记对象不适合作为偏向锁。最后唤醒暂停的线程。

JVM怎么开启/关闭偏向锁?

偏向锁在jdk1.6之后是默认开启的。

通过jvm的参数-XX:-UseBiasedLocking,可以关闭偏向锁,然后默认会进入轻量级锁。

通过jvm的参数-XX:+UseBiasedLocking

-XX:BiasedLockingStartupDelay=0,可以开启偏向锁,并且设置偏向锁的启动延迟为0(这个值默认为5秒,因为jvm认为系统刚刚启动的时候资源竞争是很激烈的。我们把这个值改为0,方便测试。)

我们可以来看一下,开启和关闭偏向锁之后,系统的差距


我们分别用两个参数来运行这段代码:

1、关闭偏向锁。-XX:-UseBiasedLocking

运行结果如下:

2、开启偏向锁。-XX:+UseBiasedLocking-XX:BiasedLockingStartupDelay=0

通过这个结果,我们可以大概的得出结论:在本例子中,完全无锁的情况下,开启偏向锁比关闭偏向锁,性能提升了5%到10%。


四、轻量级锁

轻量级锁(Lightweight Locking)本意是为了减少多线程进入互斥的几率,并不是要替代互斥。它利用CAS尝试在进入互斥前,进行补救,避免调用操作系统层面的重量级互斥锁。

线程A获得锁,会在线程A的栈帧里创建lock

record(锁记录变量),让lock record的指针指向锁对象的对象头中的mark word.再让mark word指向lock record.这就是获取了锁。

轻量级锁,线程B在锁竞争时,发现锁已经被线程A占用,则线程B不进入内核态,让线程B自旋(自旋的事情我们后面再讲),执行空循环,等待线程A释放锁。如果,完成自旋策略还是发现线程A没有释放锁,或者让线程C占用了。则线程B试图将轻量级锁升级为重量级锁。


五、重量级锁

重量级锁,就是让争抢锁的线程从用户态转换成内核态,让CPU借助操作系统进行线程协调。


六、自旋锁

前面在讲轻量级锁的时候,我们已经提到了自旋。本质就是不让出CPU,执行空循环,然后等待拿锁。

使用自旋锁后,线程被挂起的几率相对减少,线程执行的连贯性相对加强。因此,对于那些锁竞争不是很激烈,锁占用时间很短的并发线程,具有一定的积极意义。但是,对于锁竞争激烈,单线程锁占用很长时间的并发程序,自旋锁在自旋等待后,如果依然无法获得对应的锁,反而浪费了系统的资源。

我们来看下自己写的一个自旋锁。


在JDK1.6中,Java虚拟机提供-XX:+UseSpinning参数来开启自旋锁,使用-XX:PreBlockSpin参数来设置自旋锁等待的次数,默认是10次。

在JDK1.7开始,自旋锁的参数被取消,虚拟机不再支持由用户配置自旋锁,自旋锁总是会执行,自旋锁次数也由虚拟机自动调整,也就是开始使用自适应自旋锁。

七、自适应自旋锁

自适应意味着自旋的次数或者时间不再是固定的,而是由前一次在同一个锁上的自旋时间以及锁拥有者的状态来决定。如果在同一个锁对象上,自旋等待刚好成功获得锁, 并且在持有锁的线程在运行中,那么虚拟机就会认为这次自旋也是很有可能获得锁, 进而它将允许自旋等待相对更长的时间。


总结:

这些东西可能在写代码的时候完全用不到,正常情况下,只需要写个synchronized就完事了。但是,在虚拟机调优方面还是很有用的。当然,面试的时候也很有用。


参考资料:

http://www.cnblogs.com/shangxiaofei/p/5569879.html

http://www.cnblogs.com/javaminer/p/3889023.html

http://www.cnblogs.com/think-in-java/p/5520462.html

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

推荐阅读更多精彩内容