首页 > 其他分享 >探“锁”源头:synchronized、偏向锁与锁膨胀的秘密!

探“锁”源头:synchronized、偏向锁与锁膨胀的秘密!

时间:2024-12-18 12:32:05浏览次数:3  
标签:synchronized 源头 对象 代码 Markword 线程 偏向

大家好,我是程序视点的小二哥!今天我们来聊聊Java中的锁!

  • synchronized怎么用?
  • 锁是什么?
  • 偏向锁是什么?
  • 锁如何升级?何为膨胀?
  • 自旋锁何解?
  • 互斥锁怎么来的?
  • 何时要禁用偏向锁和轻量级锁?
带着上面疑问,我们一起来解“锁”疑惑!以上问题会分成几篇文章来讲,方便大家记忆!欢迎持续关注【程序视点】,这样就不会错过之后的精彩内容啦! 前言 每一个刚接触多线程并发编程的同学,当被问到,如果多个线程同时访问一段代码,发生并发的时候,应该怎么处理?     我相信闪现在脑海中的第一个解决方案就是用synchronized,让这段代码同一时间只能被一个线程执行。 synchronized的疑惑 我们也知道,synchronized关键字可以用在方法上,也可以用在代码块上,如果要使用synchronized,我们一般就会如下使用:
public synchronized void doSomething() { //do something here}
或者
synchronized(LockObject) { //do something here}
那么实际上,synchronized关键字到底是怎么加锁的?锁又长什么样子的呢? 关于锁,还有一些什么样的概念需要我们去认识,去学习,去理解的呢? 以前在学习synchronized的时候,就有文章说, synchronized是一个很重的操作,开销很大,不要轻易使用,我们接受了这样的观点,但是为什么说是重的操作呢,为什么开销就大呢? 到java1.6之后,java的开发人员又针对锁机制实现了一些优化,又有文章告诉我们现在经过优化后,使用synchronized并没有什么太大的问题了,那这又是因为什么原因呢?到底是做了什么优化? 那今天我们就尝试着从锁机制实现的角度,来讲述一下synchronized在java虚拟机上面的适应场景是怎么样的。 由于java在1.6之后,引入了一些优化的方案,所以我们讲述synchronized,也会基于java1.6之后的版本。 锁对象 首先,我们要知道锁其实就是一个对象,java中每一个对象都能够作为锁。 所以我们在使用synchronized的时候,
  1. 对于同步代码块,就得指定锁对象。
  2. 对于修饰方法的synchronized,默认的锁对象就是当前方法的对象。
  3. 对于修饰静态方法的synchronized,其锁对象就是此方法所对应的类Class对象。
我们知道,所谓的对象,无非也就是内存上的一段地址,上面存放着对应的数据,那么我们就要想,作为锁,它跟其它的对象有什么不一样呢?怎么知道这个对象就是锁呢?怎么知道它跟哪个线程关联呢?它又怎么能够控制线程对于同步代码块的访问呢? Markword 可以了解到在虚拟机中,对象在内存中的存储分为三部分:
  1. 对象头
  2. 实例数据
  3. 对齐填充
其中,对象头填充的是该对象的一些运行时数据,虚拟机一般用2到3个字宽来存储对象头。
  1. 数组对象,会用3个字宽来存储。
  2. 非数据对象,则用2个字宽来存储。
其结构简单如下:
长度 内容 说明
32/64bit Markword hashCode,GC分代年龄,锁信息
32/64bit Class Metadata Address 指向对象类型数据的指针
32/64bit Array Length 数组的长度(当对象为数组时)
从上表中,我们可以看到,锁相关的信息,是存在称之为Markword中的内存域中。 拿以下的代码作为例子, synchonized(LockObject) { //do something here} 在对象LockObject的对象头中,当其被创建的时候,其Markword的结构如下:
bit fields   是否偏向锁 锁标志位
hash age 0 01
从上面Markword的结构中,可以看出 所有新创建的对象,都是可偏向的(锁标志位为01),但都是未偏向的(是否偏向锁标志位为0) 偏向锁 当线程执行到临界区(critical section)时,此时会利用CAS(Compare and Swap)操作,将线程ID插入到Markword中,同时修改偏向锁的标志位。 这说明此对象就要被当做一个锁来使用,那么其Markword的内容就要发生变化了。 其结构其会变成如下:
bit fields    是否偏向锁 锁标志位
threadId epoch age 1 01
可以看到,
  1. 锁的标志位还是01
  2. “是否偏向锁”这个字段变成了1
  3. hash值变成了线程ID和epoch值
也就是说,这个锁将自己偏向了当前线程,心里默默地藏着线程id, 在这里,我们就引入了“偏向锁”的概念。 在此线程之后的执行过程中,如果再次进入或者退出同一段同步块代码,并不再需要去进行加锁或者解锁操作,而是会做以下的步骤:
  1. Load-and-test,也就是简单判断一下当前线程id是否与Markword当中的线程id是否一致.
  2. 如果一致,则说明此线程已经成功获得了锁,继续执行下面的代码
  3. 如果不一致,则要检查一下对象是否还是可偏向,即“是否偏向锁”标志位的值。
  4. 如果还未偏向,则利用CAS操作来竞争锁,也即是第一次获取锁时的操作。
  5. 如果此对象已经偏向了,并且不是偏向自己,则说明存在了竞争。此时可能就要根据另外线程的情况,可能是重新偏向,也有可能是做偏向撤销,但大部分情况下就是升级成轻量级锁了。
以下是Java开发人员提供的一张图:     “偏向锁”是Java在1.6引入的一种优化机制,其核心思想在于,可以让同一个线程一直拥有同一个锁,直到出现竞争,才去释放锁。 因为经过虚拟机开发人员的调查研究,在大多数情况下,总是同一个线程去访问同步块代码,基于这样一个假设,引入了偏向锁,只需要用一个CAS操作和简单地判断比较,就可以让一个线程持续地拥有一个锁。 也正因为此假设,在Jdk1.6中,偏向锁的开关是默认开启的,适用于只有一个线程访问同步块的场景。 下篇预告 在上面,我们说到,一旦出现竞争,也即有另外一个线程也要来访问这一段代码,偏向锁就不适用于这种场景了。 如何解决的呢?下篇文章将带大家了解锁膨胀、锁撤销、轻量级锁等内容!持续关注,这样就不会错过之后的精彩内容啦! 如果这篇文章对你有帮助的话,别忘了【点赞】【分享】支持下哦~

标签:synchronized,源头,对象,代码,Markword,线程,偏向
From: https://www.cnblogs.com/tanggoahead/p/18614575

相关文章

  • JavaEE初阶——多线程4(线程安全 和 解决办法(synchronized))
    线程不安全原因小结:1.【根本原因】操作系统上的线程是“抢占式执行”“随机调度”=>线程之间执行顺序有很多变数(罪魁祸首,万恶之源)2.代码结构:代码中,多个线程,同时,修改,同一个变量。、如果只是读取,变量的内容是固定不变的。如果是两个不同变量,彼此之间就不会产生相互覆盖......
  • 源头厂家短视频矩阵源码开发全流程与优势解析
    在当今数字化时代,短视频平台蓬勃发展,短视频矩阵应运而生,所谓短视频矩阵,就是指在多个短视频平台(如抖音、快手、视频号等)建立多个账号,并通过系统的运营策略将这些账号关联起来,形成一个有机整体,以实现品牌推广、流量增长、用户覆盖范围扩大等多项目标。短视频矩阵能够大幅拓展......
  • 短视频矩阵系统开发,源头工厂OEM搭建揭秘!
    在当前这个信息充斥的时代,矩阵系统的视频剪辑、批量账号管理发布、以及评论和私信的高效管理功能,已经成为企业和个人在运营自媒体时不可或缺的强大工具。借助这些工具,我们能够高效地进行内容创作、发布和管理工作,显著提升工作效率与成效。矩阵系统剪辑作为一种高效的视频编......
  • 实现电脑控制手机群控:使用最新技术免越狱开发源头手机群控
    随着移动设备在企业和个人生活中的广泛应用,对多台iOS设备进行集中管理和控制的需求日益增长。传统的越狱方式虽然能解锁更多功能,但伴随着系统稳定性下降、安全性减弱等风险。相比之下,基于最新技术的免越狱群控系统提供了一种更为安全、高效的解决方案。本章将详细介绍如何利用......
  • synchronized同步锁机制
    目录synchronized的使用Java的对象头和Monitor对象头实例数据对齐填充synchronized原理synchronized修饰代码块示例对象锁的四种状态无锁偏向锁轻量级锁重量级锁synchronized的使用如果修饰的是具体对象:锁的是对象如果修饰的是成员方法:那锁的就是this如果修饰的是静态......
  • java 多线程传统锁:synchronized,Lock锁
    传统锁:synchronized是内置关键词,无法获取锁的状态Lock锁:类是否获取到锁,需手动释放锁publicclassSaleTicketDem{publicstaticvoidmain(String[]args){Ticket2t=newTicket2();newThread(()->{for(inti=0;i<40;i++){t.sale();;}},"a").start();n......
  • 抖音短视频矩阵怎么做?源头矩阵厂家深度解析矩阵玩法
    在2024年激烈的市场竞争中,企业要想实现业绩的飞跃,就必须突破流量的瓶颈。短视频作为新兴的流量聚集地,企业需要迅速把握机遇,打造一个强大的短视频网络。谁能抢先一步行动,谁就能在这场流量争夺战中取得先机。今天,笔者一文给大家聊清楚,什么是短视频矩阵?实体行业为什么要做短视......
  • 设计图纸外发安全:从源头到终端的全方位保护!
    很多企业都会涉及到设计图纸外发的场景,通常与企业的业务需求和合作模式密切相关。比如汽车行业、基建行业、航空航天行业、科技行业、军工行业等,在传输设计图纸时都面临着设计图纸安全收发、合规有效等方面的挑战和需求。具体如下:1.汽车行业:除了汽车制造,汽车行业还包括汽车零部件......
  • Java同步机制深度解析: synchronized vs ReentrantLock
    目录1.引言2.synchronized关键字2.1基本用法2.2实现原理2.2.1Java对象头2.2.2Monitor对象2.3锁升级过程2.4锁消除和锁粗化2.5自旋锁与自适应自旋锁2.6synchronized的特性3.ReentrantLock3.1基本用法3.2实现原理3.2.1AQS的核心思想3.2.2ReentrantLock的......
  • 并发编程中锁Synchronized和ReentrantLock,CAS,AQS理解
    SynchronizedJAVA关键字,独占式的悲观锁,可重入锁。主要解决多个线程之间的访问资源的同步性,可以保证被他修饰的方法或者代码块在任意时刻只能有一个线程执行早期是重量级锁,JAVA6后引入大量优化,自旋锁,适应性自旋锁,偏向锁,轻量级锁,锁消除,锁粗化减少锁的开销使用方式修饰......