专注Java教育14年 全国咨询/投诉热线:400-8080-105
动力节点LOGO图
始于2009,口口相传的Java黄埔军校
首页 学习攻略 Java培训 Java培训教程:Java多线程详解之Synchronized的底层实现

Java培训教程:Java多线程详解之Synchronized的底层实现

更新时间:2020-01-02 15:15:54 来源:动力节点 浏览1939次


  Java面试的时候经常会被问到Java多线程相关的问题,尤其喜欢问:


  synchronized的底层实现原理


  synchronized锁与JVM的关系


  synchronized的锁升级顺序


  synchronized的锁优劣势与应用场景


  今天主要分享以上内容,详解synchronized的底层实现。


  Synchronized(同步锁)


  synchronized 翻译为中文的意思是同步,也称之为”同步锁“。


  synchronized的作用是保证在同一时刻, 被修饰的代码块或方法只会有一个线程执行,以达到保证并发安全的效果。


  Synchronized的使用


  1.synchronized的3种使用方式


  修饰实例方法:作用于当前实例加锁


  修饰静态方法:作用于当前类对象加锁


  修饰代码块:指定加锁对象,对给定对象加锁


  2.synchronized的代码范例


Java培训教程:Java多线程详解之Synchronized的底层实现


  Synchronized的底层实现


  synchronized的底层实现是完全依赖与JVM虚拟机的。


  所以谈synchronized的底层实现,就不得不谈数据在JVM内存的存储:Java对象头,以及Monitor对象监视器。


  1.Java对象头


  在JVM虚拟机中,对象在内存中的存储布局,可以分为三个区域:


  对象头(Header)


  实例数据(Instance Data)


  对齐填充(Padding)


  Java对象头主要包括两部分数据:


  类型指针(Mark Word):是对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例;


  标记字段(Klass Pointer):用于存储对象自身的运行时数据,如哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程 ID、偏向时间戳等等,它是实现轻量级锁和偏向锁的关键.


  2.Java锁对象存储位置


  所以,很明显synchronized使用的锁对象是存储在Java对象头里的标记字段里。


  3.Monitor


  synchronized的对象锁,其指针指向的是一个monitor对象(由C++实现)的起始地址。每个对象实例都会有一个 monitor。


  Monitor描述为对象监视器,可以类比为一个特殊的房间,这个房间中有一些被保护的数据,Monitor保证每次只能有一个线程能进入这个房间进行访问被保护的数据,进入房间即为持有Monitor,退出房间即为释放Monitor。


  使用syncrhoized加锁的同步代码块在字节码引擎中执行时,主要就是通过锁对象的monitor的取用与释放来实现的。


  4.线程状态流转


  当多个线程同时请求某个monitor时,monitor会设置几种状态用来区分请求的线程:


  Contention List:所有请求锁的线程将被首先放置到该竞争队列


  Entry List:Contention List中那些有资格成为候选人的线程被移到Entry List


  Wait Set:那些调用wait方法被阻塞的线程被放置到Wait Set


  OnDeck:任何时刻最多只能有一个线程正在竞争锁,该线程称为OnDeck


  Owner:获得锁的线程称为Owner


  !Owner:释放锁的线程


  下图反映了个状态转换关系


Java培训教程:Java多线程详解之Synchronized的底层实现


  Synchronized 锁的升级


  锁解决了数据的安全性,但是同样带来了性能的下降。hotspot 虚拟机的作者经过调查发现,大部分情况下,加锁的代码不仅仅不存在多线程竞争,而且总是由同一个线程多次获得。所以基于这样一个概率。


  synchronized 在JDK1.6 之后做了一些优化,为了减少获得锁和释放锁来的性能开销,引入了偏向锁、轻量级锁、自旋锁、重量级锁,锁的状态根据竞争激烈的程度从低到高不断升级。


  1.偏向锁


  偏向锁是JDK6中引入的一项锁优化,大多数情况下,锁不仅不存在多线程竞争,而且总是由同一线程多次获得,为了让线程获得锁的代价更低而引入了偏向锁。


  偏向锁会偏向于第一个获得它的线程,如果在接下来的执行过程中,该锁没有被其他的线程获取,则持有偏向锁的线程将永远不需要同步。


  2.轻量级锁


  如果明显存在其它线程申请锁,那么偏向锁将很快升级为轻量级锁。


  3.自旋锁


  自旋锁原理非常简单,如果持有锁的线程能在很短时间内释放锁资源,那么那些等待竞争锁的线程就不需要做内核态和用户态之间的切换进入阻塞挂起状态,它们只需要等一等(自旋),等持有锁的线程释放锁后即可立即获取锁,这样就避免用户线程和内核的切换的消耗。


  4.重量级锁


  指的是原始的Synchronized的实现,重量级锁的特点:其他线程试图获取锁时,都会被阻塞,只有持有锁的线程释放锁之后才会唤醒这些线程。


35 拷贝.jpg


       以上就是动力节点Java培训机构小编介绍的“Java培训教程:Java多线程详解之Synchronized的底层实现”的内容,希望对大家有帮助,如有疑问,请在线咨询,有专业老师随时为你服务。


  相关内容


  Java多线程编程详解


  java多线程的状态转换以及基本操作


  JAVA多线程实现的四种方式


  Java多线程学习,深入解析


  常见Java多线程面试题总结


提交申请后,顾问老师会电话与您沟通安排学习

免费课程推荐 >>
技术文档推荐 >>