Open yisaca opened 4 years ago
#### 偏向锁撤销(InterpreterRuntime::monitorenter)流程 # 0 JVM使用偏向锁开关打开 0.1 直接调用 ObjectSynchronizer::fast_enter # 1 JVM使用偏向锁开关关闭 0.1 直接调用 ObjectSynchronizer::slow_enter #### ObjectSynchronizer::fast_enter # 0 JVM使用偏向锁开关打开 0.1 系统非处于safepoint,调用 revoke_and_rebias 0.1.1 返回值是 BIAS_REVOKED_AND_REBIASED 直接退出,否则执行0.1.2 0.1.2 执行slow_enter 0.2 当前系统处于safepoint,执行revoke_at_safepoint,继续执行slow_enter 0.3 到此步锁对象应该是非偏向模式,否则报错 # 1 JVM偏向锁开关关闭 1.1 直接执行slow_enter #### revoke_and_rebias # 注意:根据偏向锁获取逻辑,进入revoke_and_rebias会有多种case 1 类关闭偏向情况 [LockRecord_addrss](竞争成功的线程已经将mark改为自己栈上的LockRecord地址) 2 epoch过期情况 [suc_thread|epoch|age|*|101] 3 偏向线程竞争情况 [suc_thread|epoch|age|*|101] 1、2、3三种竞争情况都可以细化为: (a) 首次抢锁Thread_A和首次抢锁Thread_B同时竞争匿名线程的情况 (b) 首次抢锁Thread_D遇到已经偏向曾经成功抢锁Thread_C的情况 因此调用revoke_and_rebias的入参的mark情况比较多 # 1 如果对象匿名偏向且不需要尝试重偏向(匿名偏向[nothread|*|*|101] && attempt_rebias=false) 1.1 尝试更新锁对象,将对象头hash置为0 & 锁状态置为无锁(001)& 分代年龄置为当前对象的分代[nohash|age|001] 1.2 如果成成,返回BIAS_REVOKED(外层认为失败,会调用slow_eneter),否则执行0.3 1.3 根据heuristic进行操作 # 2 如果对象是偏向模式(mark的最后三位101) 2.1 类关闭偏向锁 2.1.1 尝试直接将锁对象的mark替换为类的header 2.1.2 不管是否成功都返回BIAS_REVOKED(外层认为失败,会调用slow_eneter),否则执行1.3 2.2 对象epoch过期 2.2.1 尝试重定向 2.2.1.1 尝试更新锁对象,将线程更新为当前线程&分代为锁对象的分代&epoch为class的epoch 并且当前线程和上一轮竞争获胜线程一致 [当前thread|prototype的epoch|当前对象age|101] 2.2.1.2 如果成功直接返回BIAS_REVOKED_AND_REBIASED(外层认为重定向成功),否则执行2.1.3 2.2.1.3 根据heuristic进行操作 2.2.2 不需要尝试重定向 2.2.2.1 尝试更新锁对象,将对象头hash置为0 & 锁状态置为无锁(001)& 分代年龄置为锁对象的分代 [nohas|age|001] 2.2.2.2 如果成功返回 BIAS_REVOKED(外层认为失败,会调用slow_eneter),否则执行2.2.3 2.2.2.3 根据heuristic状态进行操作 ...... 其他场景进入3 # 3 更新heuristic 3.1 锁对象非偏向模式,返回 HR_NOT_BIASED 3.2 如果之前批量重定向过&&经过比较长的时间才发生本次撤销&&撤销次数区间在(批量重定向阈值,批量撤销阈值]之间 3.2.1 更新类的撤销次数复位为0 3.3 如果更新后的撤销次数等于批量撤销阈值,返回 HR_BULK_REVOKE 3.4 如果更新后的撤销次数等于批量重定向阈值,返回 HR_BULK_REBIAS 3.5 返回HR_SINGLE_REVOKE # 4 根据更新heuristic的结果进行处理 4.1 如果更新heuristic返回 HR_NOT_BIASED,则向外层返回 NOT_BIASED(外层认为失败,会调用slow_eneter) 4.2 如果如果更新heuristic返回 HR_SINGLE_REVOKE 4.2.1 如果锁对象的thread是当前线程&&锁对象epoch没过期,直接调用 revoke_bias 并返回结果到外层,否则执行4.2.2 4.2.2 VMThread执行撤销 revoke并返回结果到外层 4.3 如果如果更新heuristic返回HR_BULK_REVOKE或者HR_BULK_REBIAS,VMThread执行撤销 bulk_revoke并返回结果到外层 #### revoke_bias (函数签名BiasedLocking::Condition revoke_bias(oop obj, bool allow_rebias, bool is_bulk, JavaThread* requesting_thread)) # 0 锁对象的mark不是偏向锁模式(最后三位不是101),返回 NOT_BIASED # 1 如果锁对象是匿名偏向 1.1 如果 revoke_bias的方法入参不允许重偏向(allow_rebias),修改锁对象为非偏向模式(nohash|当前对象age|001) 1.2 返回 BIAS_REVOKED # 2 如果锁对象偏向的线程非存活状态 2.1 如果revoke_bias的方法入参允许重偏向(allow_rebias),修改锁对象为可偏向模式(nothread|当前对象age|101) 2.2 如果revoke_bias的方法入参不允许重偏向(allow_rebias),修改锁对象为非偏向模式(nohash|当前对象age|001) 2.3 返回 BIAS_REVOKED # 3 如果锁对象偏向线程存活 3.1 找到偏向线程的栈上所有objectRef指向锁对象的LockRecord,将所有找到的LockRecord的displaced_header值置为NULL 3.1.1 如果3.1中找到最早获取锁的LockRecord 3.1.1.1 LockRecord的header置为非偏向模式(nohash|当前对象age|001) 3.1.1.2 锁对象的mark置为LockRecord的指针 3.1.2 如果3.1中没有找到最早获取锁的LockRecord 3.1.2.1 如果revoke_bias的方法入参允许重偏向(allow_rebias),修改锁对象为可偏向模式(nothread|当前对象age|101) 3.1.2.2 如果revoke_bias的方法入参不允许重偏向(allow_rebias),修改锁对象为非偏向模式(nohash|当前对象age|001) 3.2 返回 BIAS_REVOKED #### bulk_revoke_or_rebias_at_safepoint (oop o, bool bulk_rebias, bool attempt_rebias_of_object,JavaThread* requesting_thread) //主要是对所属类修改epoch以及已经发生偏向的对象的epoch,对于已经构造好但是还没有被作为锁使用的同类对象,会出现实例和类epoch不一致情况 # 1 如果是批量重偏向 1.1 如果锁对象所属类没有关闭偏向模式 1.1.1 获取prev_epoch,批量重偏向会对类的epoch加1,获取cur_epoch 1.1.2 遍历所有线程的所有栈,找到属于(当前锁对象所属类)的其他锁对象 1.1.2.1 如果其他锁对象是偏向模式(mark最后三位101),修改其他对象的epoch为cur_epoch 1.1.2.2 如果其他锁对象不是偏向模式,什么都不做 1.2 如果锁对象所属类已经关闭偏向模式,什么都不做 1.3 对当前锁对象执行 revoke_bias(入参allow_rebais == 锁对象所属类是偏向模式&&方法入口入参attempt_rebias_of_object期望尝试重偏向) // 1 和 2 互斥 # 2 如果是批量撤销 2.1 更新锁对象所属类为非偏向模式([nohash|age|001]) 2.2 遍历所有线程栈,找到属于(当前锁对象所属类)的其他锁对象 2.2.1 如果如果其他锁对象是偏向模式(mark最后三位101),调用revoke_bias,其中入参allow_rebais默认为false 2.2.2 如果其他锁对象不是偏向模式,什么都不做 2.3 对当前锁对象执行 revoke_bias,入参allow_rebais指定为false # 3 初始化 status_code = BiasedLocking::BIAS_REVOKED # 4 如果当前锁对象是偏向模式 && 锁对象所属类是偏向模式 4.1 锁对象的mark更新为[当前线程id|当前对象age|类的epoch|101] 4.2 更新status_code = BiasedLocking::BIAS_REVOKED_AND_REBIASED # 5 返回 status_code
add some example entry cases to revoke_and_rebais
add "bulk_revoke_or_rebias_at_safepoint" part