Object.wait和Thread.sleep源码

面试被问到了wait和sleep区别,才知道这种使用场景完全不同的东西还能问区别…不过,确实没看过这俩的源码,来看一下。

解释器映射op的过程

我这里看的是art源码,而非jvm源码。本人对bytecode到真正执行代码的映射暂无认知,经高人指点是所有的解释器实现是在interpreter目录中。

入口是interpreter.cpp#EnterInterpreterFromInvoke -> Execute -> ExecuteSwitch -> interpreter_switch_impl.h#ExecuteSwitchImpl -> ExecuteSwitchImplCpp -> interpreter_switch_impl-inl.h#OP_NAME(见list

Monitor enter和exit

这个是基础,因为wait必须在monitor保护下。monitor相关的背景知识

monitor#enter

interpreter_switch_impl-inl.h#MONITOR_ENTER -> 这里会把寄存器里的对象拿出来,传给interpreter_common.h#DoMonitorEnter -> object-inl.h#MonitorEnter -> monitor.cc#MonitorEnter

  • 获取锁字段,Object#GetLockWord,锁字段是在对象头中的32bit数据
  • 根据锁类型来进行下一步操作
    • 无锁,直接锁上thin lock
    • thin lock,检查thin lock owner(thread id)是否与当前线程id相同。
      • 如果相同,获取thin lock个数,未超阈值会更新lock word,如果更新失败会有个自旋;超过阈值会InflateThinLocked。(获取的时候都会调用CheckReadBarrierState,没看懂干嘛了。)
      • 如果不同,会自旋尝试获取thin lock阈值次。如果超过自旋阈值会先yeild,再等待调度;如果未超会InflateThinLocked。
    • fat lock,因为有多线程,所以先atomic_thread_fence保护上。然后LockWord#FatLockMonitor(返回一个Monitor对象)-> Monitor#(Try)Lock
      • TryLock,基本上就是操作c++的mutex了,如果成功就直接return了
      • 大概率当前线程不是Monitor的owner
      • 把自己设置到线程的SetMonitorEnterObject上
      • 靠mutex获取锁,释放cpu
      • 锁获取成功,修改owner

monitor#InflateThinLocked

  • 看起来是利用TheadList来做等待的 // TODO
  • 利用MonitorPool构造一个Monitor
  • Monitor#Install,替换对象头
  • 加到MonitorList中。看起来只是为了不释放?

Object#wait

仍然是走到了Monitor#wait,整体就是一个线程等待队列,类似于AQS,核心是AppendToWaitSet和RemoveFromWaitSet。

Thread#sleep

Thread持有一个Object对象,叫做lock。Sleep是拿到这个对象后传给了native。
java_lang_Thread.cc#Thread_sleep -> Monitor#wait !!!这里居然是直接调用wait,面试官站出来,这俩有什么区别!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值