范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

虚拟机中对象锁实现分析

  一、前言
  编程过程中经常会遇到线程的同步问题,Java 中对同步问题的解决方案比较多(synchronized、JUC、原子操作、volatile、条件变量等),其中synchronized 最方便、简单易用,也是java 编程中使用最多的临界区保护方案。本文主要讲述对象锁的相关知识,详细介绍synchronized 和Object 的关键方法的虚拟机实现原理。
  二、Java 对象锁的使用方式
  2.1 实例方法的同步
  synchronized 修饰实例方法,该同步仅对当前对象的该方法起作用,同一时间只能有一个线程可以进入该对象的此方法。对于不同对象的此函数,无法做到互斥保护。
  2.2 静态方法的同步
  synchronized 修饰静态方法,该同步对当前类对象的该方法起作用,同一时间只能有一个线程可以进入该方法。
  2.3 代码块的同步
  在大多少情况下,并不需要对整个方法进行保护,当synchronized 修饰代码块时,该代码块的访问依赖于object 对象锁的互斥访问,同一时间只能有一个线程持有object 对象锁。
  更准确的来讲,synchronized 关键字是依赖于对象锁而生效的,每个synchronized 同步块开始的地方都会生成monitor-enter obj指令,同步块结束的地方生成monitor-exit obj 的指令,其中obj 为用于控制互斥访问的对象。同一时间只能有一个线程持有obj 的对象锁。在2.1 中synchronized 依赖的是实列对象,2.2 中synchronized 依赖的是类对象,2.3 中synchronized 依赖的是object 对象。
  当一个对象控制多个代码块时,多个代码块也是互斥访问,如下面代码:
  代码块①和代码块② 虽然在两个函数中,但是synchronized 依赖的对象都为object,这两个代码块也是互斥访问。
  2.4 Object wait() 和notify() 使用方法
  Object 作为所有类的基类,都实现了object方法。典型的用法如下:
  thread 1持有object 对象锁,并调用object.wait() 方法后,则该线程进入WAITING状态,并释放object 对象锁,等待其它线程来唤醒它。
  当thread 2 持有object 对象锁,并调用object.notify()方法后,唤醒thread 1,thread 1
  重新获得object 对象锁继续执行。Object类方法说明:
  三、Android对象内存结构
  3.1 对象内存结构
  一个类的实例对象内存主要由3部分组成:
  1). 对象头:对象头包括kclass_和monitor_两个字段,其中kclass_ 存放指向类对象的指针,通过该指针可以找到该对象对应的类,monitor_ 用于存放对象运行时的标识数据,例如: GC 标志位、哈希码、锁状态等信息,后面详细分析。
  2). 实例数据,该部分存放实例变量值,父类实例变量值在前,子类在后,且实例变量值按照如下顺序进行排序:
  3).对齐填充,对象在内存中是按照8byte 对齐的,如果实例数据部分没有按照8byte对齐,则填充为8byte 对齐。
  3.2 monitor_ 字段分析
  monitor_ 字段定义在art/runtime/mirror/object.h,类型为uint32_t,主要有下面3个操作函数。
  操作函数中SetLockWord和CasLockWord函数的入参或GetLockWord函数的返回值都包含LockWord 变量,对monitor_ 字段的操作是通过LockWord 的值进行的。
  下面再来看LockWord 定义:
  LockWord 类的定义在art/runtime/lock_word.h 文件中,从注释中可以看到LockWord的使用主要有4种状态,如下:
  LockWord 的设计非常精妙,一个32 位数据的每一位都充分利用,而且很好的区分了不同状态。下面对各状态进行详细说明: unlocked/thin 状态下31-30 bit 为00,默认状态下为unlocked 状态,当对象进行线程同步时变成thin lock 状态,27-16bit 记录了thin lock重入的次数,15-0 bit 记录了持有该thin lock的线程ID。 fat lock状态下31-30 bit 为01,当对象锁在thin lock状态,且有新的(非owner)线程与其竞争,经过适当的等待期(sched_yield调用、循环获取thin lock 状态)后依然无法拿到锁,则转换为fat lock 状态,并为该对象分配一个Monitor 资源。 hash state状态下31-30 bit 为10,在27-0 bit 存储对象的hash code,当在其它模式下,hash code 会存储在该对象关联的Monitor 对象中。 forwarding address state 状态下31-30 bit 为11,在concurrent copying GC 的copy 阶段,当一个对象被拷贝后,指向拷贝后的对象地址,当线程访问到该对象后,通过该转发地址,访问新的对象。
  第29 位为mark bit,通过该bit位可以快速判断是否标记过,避免重复标记。
  第28 位为read barrier bit,如果对象LockWorkd的该bit 被设置,则在访问该对象的成员时会进入慢速路径,判断对象是不是需要更新,如果需要更新,则返回拷贝后的对象地址。
  四、对象锁代码分析
  4.1 首先我们看一段代码
  这段代码比较简单,主要有下面两个核心点:
  1). 在主线程执行的过程中,用obj 对象进行线程同步,并调用obj.wait()函数,使线程阻塞在了obj 对象锁上等待唤醒。
  2). main函数中创建匿名线程,该线程首先sleep 2000ms,然后唤醒阻塞在obj 对象锁上线程。
  4.2编译TestDemo.java,命令如下:
  1).Javac 将TestDemo.java 文件编译生成TestDemo*.class文件,java 编译过程中每个类会生成一个class 文件。
  2).d8 命令将TestDemo*.class 文件通过编译、重构、重排、压缩、混淆后生成对应的dex (Dalvik Executable file)格式文件。
  3).dexdump.exe命令可以查看dex 文件格式的详细信息,如校验信息、dex 头信息、生成dex 的CFG 信息、dex 的反汇编信息等,详细使用方法可以通过dexdump.exe –help 命令查看
  通过dexdump.exe –d classes.dex 查看反汇编
  其中run 方法指令信息如下:
  main 函数的指令信息如下:
  对部分指令解析如下:
  对于dex 指令详细格式可以阅读google 的官方文档:
  https://source.android.com/docs/core/runtime/dalvik-bytecode
  本文重点分析monitor-enter、monitor-exit、Object.wait()、Object.notify()在虚拟机中的详细实现。
  4.3.Object.wait() 流程分析
  Object.wait() 的调用关系如下:
  Object 类是所有类的父类,任何类中都可以调用public 的wait() 方法,最终调用到虚拟机的monitor.cc 文件的wait 静态方法,
  首先构造了一个操作obj 的Handle对象h_obj,通过ObjectWaitStart 函数通知jvmti 调试系统发生了JVMTI_EVENT_MONITOR_WAIT 事件。
  JVMTI(JVM Tool Interface)是 Java 虚拟机所提供的 native 编程接口,可以用来开发并监控虚拟机,可以查看JVM内部的状态,并控制JVM应用程序的执行。可实现的功能包括但不限于:调试、监控、线程分析、覆盖率分析工具等。
  首先获得h_obj 对象的LockWord 字段,lock_word.GetState()函数获得当前的锁状态,主要有下面几种情况:
  1).hash 或unlocked 状态:
  因为调用wait()方法必须持有对象锁,所以不会出现这两种状态,如果出现则抛出IllegalMonitorStateException 异常。
  2).thin lock 状态:
  当持有该对象锁的线程不是要wait 的线程,也抛出IllegalMonitorStateException 异常,当持有锁的线程与要wait 的线程一致,这时需要将thin lock inflate 为fat lock,inflate 的过程在monitor-enter 指令分析中分析。
  当对象锁inflate 为fat lock 状态后,调用Monitor 对象的实例方法Wait让线程进入sleep 状态等待。
  4.4 Object.notify() 流程分析
  这里我们直接分析DoNotify 函数:
  通过lock_word.GetState() 获得当前obj 对象的锁状态,主要有下面情况:
  1) hash 或unlocked 状态 :
  抛出IllegalMonitorStateException 异常。
  2).thin lock 状态:
  当持有该对象锁的线程不是要notify 的线程,也抛出IllegalMonitorStateException 异常,当持有锁的线程与要notify 的线程一致,这时说明没有需要通知唤醒的线程,直接返回。
  3).fat lock 状态:
  在Object.notify() 流程中参数notify_all 为false,则直接调用mon->Notify(self);通知唤醒等待线程。
  4.5monitor-enter 流程分析
  对于解释执行和机器码执行模式,最终都会调用到art/runtime/mirror/object-inl.h 文件Object 对象的MonitorEnter 函数。
  下面来分析Monitor类的静态方法MonitorEnter 函数。
  FakeLock 主要用于线程安全性检查,主要在编译期检测。
  kExtraSpinIters 定义了当对象锁被其它线程持有且为thin lock 时,竞争线程循环获取锁的次数。
  通过lock_word.GetState() 获取锁状态,当锁状态为unlocked 状态时,转换为thin lock 状态,并通过cas 操作更新lock count。
  当锁状态为thin lock 状态时,首先获取锁的owner 线程id,如果owner id 与竞争线程id 一致,则有下面两种情况: 如果lock count加1小于等于(1<<12)-1(4095)时,将lock count+1 更新lock count。 如果lock count加1大于(1<<12)-1时(lock count 区域无法存储),则调用InflateThinLocked 函数对thin lock 进行膨胀。
  Atrace* 相关的函数主要用于systrace 相关信息的打印,trylock 在这里为false。
  当锁状态为thin lock 状态且锁的owner 线程id 与竞争线程id 不一致,则做一定的等待。
  runtime->GetMaxSpinsBeforeThinLockInflation() 的值为50 ,也就是说执行100 次的循环判断锁状态后,再执行50次的sched_yield() 后还未获得锁资源,如果还未拿到锁,则对该锁进行膨胀。sched_yield() 会主动让出当前线程的执行权限,并在某个时间后恢复执行。
  当锁状态已经是fat lock 状态,通过lock_word.FatLockMonitor(); 获取Monitor 对象,并通过Monitor 对象的Lock 函数让线程进入等待状态。
  当锁状态已经是hash 状态时,直接对锁进行膨胀。
  下面看锁膨胀的过程:
  thin lock 的膨胀有两种情形:
  1).lock count 的值超过了4095,这时锁的owner 为当前线程,即直接通过Inflate 函数膨胀
  2).锁的owner不是当前线程,通过SuspendThreadByThreadId 暂停锁的owner 线程(主要是owner 线程和锁膨胀线程都需要访问对象的LockWord,避免竞态问题),然后通过Inflate 进行膨胀。膨胀完成后再唤醒锁的owner 线程。
  再看Inflate 的过程:
  通过MonitorPool::CreateMonitor函数获取一个Monitor 的对象m,并通过m->install(self)函数更新对象的LockWord字段,这时LockWord 字段信息包含fat lock 状态、GC 状态、MonitorId,然后将m 保存在monitor_list_ 中。
  monitor_list_中存储了当前虚拟机使用的所有Monitor 对象。在GC 的过程中,通过该链表,访问到Monitor 依赖的对象。如果对象变成垃圾对象,则回收该Monitor,否则更新Monitor 依赖的对象信息。
  MonitorId 用于唯一标识一个Monitor,生成的方法可以看monitor_pool.h 中的实现。
  再看Monitor::Lock的过程:
  该函数的实现较长,省去调试相关的代码。
  首先介绍Monitor 中最重要的成员monitor_lock_ ,它是Mutex 的实例,通过该实例实现锁相关的核心逻辑。
  TryLock 函数主要是通过Mutex的函数实现一定的自旋等待,并设置锁的状态为线程持有的状态。
  monitor_lock_.ExclusiveLock(self);在Mutex 的ExclusiveLock函数中通过futex 系统调用实现了线程的阻塞,futex调用代码如下。
  4.6 monitor-exit 流程分析
  解释执行和机器码执行模式都会调用到MonitorExit 函数。
  通过lock_word.GetState()获取LockWord 状态,当状态为hash 或unlocked 状态时,通过FailedUnlock函数抛出异常。
  当LockWord 的状态为thin lock 状态时,有下面两种情况:
  1).锁的owner 与当前线程不一致,则出错抛出异常。
  2).锁的owner 与当前线程为同一线程,当锁有重入时,则将lock count -1,否则设置为unlocked 状态。
  当LockWord 的状态为fat lock状态时,获取该对象关联的Monitor 对象,并调用Unlock 函数
  在Unlock 函数中lock_count 为0,说明该线程不在持有该锁,通过
  SignalWaiterAndReleaseMonitorLock 唤醒阻塞在该锁上的线程。
  五、总结
  本文简单的阐述了对象锁的使用方式,对象在内存中的结构,并对对象头中关键成员LockWord 进行了分析,最后介绍了synchronized、Object.wait()和Object.notify()在虚拟机中的实现流程。
  参考文献:
  深入理解Android Java虚拟机ART 邓凡平
  深入理解java 虚拟机 周志明
  深入java 虚拟机 bill venners
  Android T 源码

一家四口缴合作医疗好多年,交了一万多,一直没用过,还继续交吗?关于农村合作医疗其本质是医疗保险的一种,只不过是由国家来推行的一种普惠政策,目的是通过农民参保,以较少的资金,结果农民看不起病住不起院的困境,对低收入群体而言是一件好事。因此,这种社保在深圳已交十七年,现回老家有影响吗?那要看你回老家前和回老家后具体如何处理社保了。处理不好,肯定会有影响的,甚至影响很大。从你的提问看,你应该属于非深圳户籍人员在深圳打工者,言语之间透露出在深圳退休的愿望,担心现在回为什么滴滴出行上很多人不接单?最早的滴滴是司机自己选择接单的顾客,现在是滴滴有个后台,顾客发出快车要求后,滴滴后台会给滴滴司机分派顾客,滴滴司机无法自己选择顾客,分派的顾客说是就近的,但是有时候也会在五公里左右买车4年了为什么每次换机油机油都不黑?说到换机油时机油的颜色深浅问题,不同的发动机这个还是有区别的,首先说说机油怎么就变黑了吧,机油变黑了主要有以下几个方面造成的,一个是机油经过长期使用氧化反应颜色变深了,不过这个不是方便面怎么做最好吃呢?hello,我是颖涵深夜的时候总是刷到罪恶泡面吃法,什么张云雷,金城武,李小鹏看着真香所以今天我们来吃泡面呀一下做了四种,全都是隐藏菜单做法,从今天开始你们再也不用单调的吃泡面了!林书豪若重返首钢,他最理想的外援搭档是大汉麦克雷还是考神?最好是考辛斯,麦克雷已经加盟欧洲球队,有人说给林书豪600万顶薪,考辛斯现在坐地起价很麻烦最近的网络舆情很尴尬,林书豪以外援签约,自然不可能的内援顶薪,甚至首钢很喜欢这样,给些代言如果排一个最近20年从来没有参加过世界杯的球星最佳阵容,怎么排?对于每一名球员来说,能够参加世界杯是无上的荣耀。但是由于种种原因,很多球星一直没有得到参加世界杯的机会。其实都不用最近20年,光是最近10年没有参加过世界杯的球星,组成的阵容已经足知道中国历史上说过的最霸气的一句话吗?扫除一切害人虫,全无敌!谢邀,我欣赏唐代诗人李白的将进酒人生得意须尽欢,莫使金樽空对月。天生我才必有用,千金散尽还复来。豪迈豁达。乐观精神。中国历史上最霸气的话,一九八二年邓小平与什么证件可以高速免费?这个问题想答全比较难,有我们知道的,也有我们不知道的。我们姑且把已知的一些罗列一些看看。平时高速免费包括法律法规规定的免费通行车辆,以及地方特殊车辆,比如军队车辆武警部队车辆,公安装宽带的师傅为什么不肯装我自己买的七类网线?我也做过移动装维,我来告诉你,我们提供的宽带到户,指的是从营运商机房到你家光猫,保证是带块足够且光衰在正常范围。光猫后面出来,我们一般会免费帮客户调试一个路由器。如果是小区有弱电箱一波接一波!曝上海男篮又挖角了,CBA名教李春江能否助其夺冠?上海挖来了富兰克林,看上了诺阿冯莱,假如继续留下弗雷戴特,上海要取代辽宁,叫板广东上海是一线大城市,他们组建CBA级别强队,按说更能和城市定位匹配,现在看是无度砸钱,球队和广东队不
MIUI14后续升级机型一览,多款小米旧机升级后更流畅了!升级说明大家不知道如何升级,可以在系统设置中点击我的设备MIUI版本来升级到MIUI14版本。目前MIUI14已经发布有一段时间了,相信大家也已经体验上了奸笑1。第一批机型目前第一8岁女孩乳房发育正常吗,是性早熟吗?在生长发育门诊科中,除了有家长咨询孩子身高的问题,也有不少家长咨询性发育的问题。比如很多家长经常问我家8岁小女孩乳房有一个小硬块,是开始发育了吗?正常吗?针对这个问题,我们来写一篇从ampampquot少生优生幸福一生ampampquot到现在允许生不能生1计划生育是我国的基本国策。2少生孩子多种树。3少生优生幸福一生。4计划生育好,政府帮养老。5同心同德把经济搞上去,群策群力把人口降下来。6优生优育搞得好,幸福生活来得早。7计划生非婚生育合法化?谁在挑战道德伦理底线!文丨崔桂忠1月30日,四川简化生育登记要求这一话题冲上热搜榜。四川省卫生健康委员会日前发布的新版四川省生育登记服务管理办法将夫妻应当在生育前进行生育登记更改为凡生育子女的公民,均应来自一位宝妈的自述很难受,不知从何说起。宝宝1岁9个月妈妈28岁作为2岁宝宝的妈妈,日复一日围绕的就是孩子,除了照顾孩子,也没有别的事情是有意义的。我是一个急功近利的人,无论什么事情都想要赶快有成果关晓彤鹿晗日本过年,住万元酒店引热议,爱情故事堪比王菲谢霆锋要说现在哪个女星最幸福,最幸运,最被爱,最受关注,那一定就是北京大妞关晓彤了。为什么,因为有鹿晗啊。这不,近日,也就是1月28日,大过年的,有网友发现关晓彤被鹿晗带去日本过年了,而网友酒吧偶遇鹿晗!现场氛围很燃,期间还开了一瓶黑桃A1月29日,有网友在某社交平台晒出了鹿晗在酒吧的视频,当天酒吧现场十分火爆,现场氛围很燃。引起大家热议。期间鹿晗时不时的还跟旁边的人交流,还会贴心的给摄像的人让位置,看到兴奋地时候陈钰琪还是很灵的文白露编辑白露是谁还在为浮图缘里步音楼与肖铎的禁忌之恋疯狂落泪?没错就是我,这个在完结之后依旧沉浸剧中无法自拔的有浮之人!大结局时,肖步活了(肖铎and步音楼)终于逃出了宫墙,再次他是张艺谋的死对头,戳着赵本山的额头大骂,发誓不与周润发合作娱评大赏张伟平012013年5月,张艺谋超生案爆发。张艺谋与无锡女子陈婷,未婚生下3名子女,江苏省无锡市滨湖区计生委,依法向张艺谋征收社会抚养费748万余元。今日头条公子误缴完罚款让关晓彤惊艳红毯的仙裙,到底是什么来头?在这个三天一红毯两天一晚会的年关,我发现,内娱已经不满足于只涛哥哥姐姐们造型的美丑。有没有高定是不是首穿品牌逼格够不够高成为被讨论的新焦点而在这场关于排面的血雨腥风中被提及最多的,Doinb金贡吐槽FPX冠军皮肤收益至今未发放去拳头门口拉CNMO新闻作为2019英雄联盟全球总决赛的冠军队伍,FPX战队在2019年11月10日以总比分30的成绩战胜来自欧洲LEC赛区的G2战队,而FPX的战队成员也收获到了当年的冠军皮