摘要:当前线程使用将对象头的替换为锁记录指针,如果成功,当前线程获得锁如果失败,表示其他线程竞争锁,当前线程便尝试使用自旋来获取锁。重量级锁是悲观锁的一种,自旋锁轻量级锁与偏向锁属于乐观锁。
操作系统在面对线程间同步的时候,会支持例如semaphore信号量和mutex互斥量等同步原语,而monitor是在编程语言中被实现的,下面介绍一下java中monitor(监视器/管程:管理共享变量以及对其的操作过程,让他们支持并发)的实现原理:
以一个阻塞队列的实现来举例:
同时,java内置的synchronized关键字可以认为是MESA模型的简化版,其只能有一个条件变量,但编译器会自动添加加锁与解锁的代码。synchronized关键字可以修饰实例方法、类方法以及代码块,如果修饰的是代码块,需要制定关联的Object;如果修饰的是实例方法,那么其关联的对象实际上是this;如果修饰的是类方法,那么其关联的对象是this.class。这些关联的对象就是MESA模型里的条件变量。
synchronized实现原理JVM基于进入和退出monitor对象来实现同步,同步代码块采用添加moniterenter、moniterexit,同步方法使用ACC_SYNCHRONIZED标记符隐式实现。每个对象都有一个monitor与之关联,运行到moniterenter时尝试获取对应monitor的所有权,获取成功就将monitor的进入数加1(所以是可重入锁,也被称为重量级锁),否则就阻塞,拥有monitor的线程运行到moniterexit时进入数减1,为0时释放monitor。
java中每个对象都有一个对象头,synchronized所用的锁就是存在对象头里的。如果是非数组的对象是8个字节(32位JVM)或者16字节(64位JVM),数组对象还会有一个数组长度(4个字节)。以32位JVM非数组对象为例:
锁信息就存在前4个字节的MarkWord中,JVM对synchronized的加锁过程优化为:
检测Mark Word里面是不是当前线程的ID,如果是,表示当前线程处于偏向锁
如果不是,则使用CAS将当前线程的ID替换Mard Word,如果成功则表示当前线程获得偏向锁,置偏向标志位1
如果失败,则说明发生竞争,撤销偏向锁,进而升级为轻量级锁。
当前线程使用CAS将对象头的Mark Word替换为锁记录指针,如果成功,当前线程获得锁
如果失败,表示其他线程竞争锁,当前线程便尝试使用自旋来获取锁。
如果自旋成功则依然处于轻量级状态。
如果自旋失败,则升级为重量级锁。
重量级锁是悲观锁的一种,自旋锁、轻量级锁与偏向锁属于乐观锁。
CAS设计读取-比较-写入三个操作,是在CPU指令层面保证其原子性,volatile是保证多线程下的内存可见性,二者需配合使用。另外还需注意CPU缓存行(一次以32/64字节为单位从主内存中读取数据到缓存)包含多个变量所带来的隐形同步问题:其中一个变量被volatile修饰,导致另外一个变量在另一个CPU核上(另一个线程)的读写也要被强制刷新缓存。
管程:并发编程的万能钥匙
java 中的锁 -- 偏向锁、轻量级锁、自旋锁、重量级锁
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/77770.html
摘要:语言在之前,提供的唯一的并发原语就是管程,而且之后提供的并发包,也是以管程技术为基础的。但是管程更容易使用,所以选择了管程。线程进入条件变量的等待队列后,是允许其他线程进入管程的。并发编程里两大核心问题互斥和同步,都可以由管程来帮你解决。 并发编程这个技术领域已经发展了半个世纪了。有没有一种核心技术可以很方便地解决我们的并发问题呢?这个问题, 我会选择 Monitor(管程)技术。Ja...
摘要:请参看前一篇文章并发学习笔记一原子性可见性有序性问题六等待通知机制什么是等待通知机制当线程不满足某个条件,则进入等待状态如果线程满足要求的某个条件后,则通知等待的线程重新执行。经极客时间并发编程实战专栏内容学习整理 请参看前一篇文章:Java 并发学习笔记(一)——原子性、可见性、有序性问题 六、等待—通知机制 什么是等待通知—机制?当线程不满足某个条件,则进入等待状态;如果线程满足要...
摘要:基本元素机制需要几个元素来配合,分别是临界区对象及锁条件变量以及定义在对象上的,操作。这个外部条件在机制中称为条件变量。提供的机制,其实是,等元素合作形成的,甚至说外部的条件变量也是个组成部分。 monitor的概念 管程,英文是 Monitor,也常被翻译为监视器,monitor 不管是翻译为管程还是监视器,都是比较晦涩的,通过翻译后的中文,并无法对 monitor 达到一个直观的描...
摘要:那并发里面的理论和模型是什么呢那便要从操作系统中解决并发问题的一种模型管程讲起了。当一个进程使用完管程后,它必须释放管程并唤醒等待管程的某一个进程。总结在并发编程领域,有两大核心问题互斥和同步,而这两个问题,管程模型都可以解决。 为什么需要了解管程 Java并发编程是Java中高级程序员必备的一项技能,但是真正学明白并发编程也并非易事。正如Java并发编程实践中的一句话编写正确的程序并...
摘要:由此可见,自旋锁和各有优劣,他们分别适用于竞争不多和竞争激烈的场景中。每一个试图进入同步代码块的线程都会被封装成对象,它们或在对象的中,或在中,等待成为对象的成为的对象即获取了监视器锁。 前言 系列文章目录 前面两篇文章我们介绍了synchronized同步代码块以及wait和notify机制,大致知道了这些关键字和方法是干什么的,以及怎么用。 但是,知其然,并不知其所以然。 例如...
阅读 3609·2021-11-23 09:51
阅读 1626·2021-10-22 09:53
阅读 1316·2021-10-09 09:56
阅读 825·2019-08-30 13:47
阅读 2109·2019-08-30 12:55
阅读 1568·2019-08-30 12:46
阅读 1044·2019-08-30 10:51
阅读 2369·2019-08-29 12:43