java的Object里wait()实现原理

    在进行wait()之前,就代表着需要争夺Synchorized,而Synchronized代码块通过javap生成的字节码中包含monitorenter和monitorexit两个指令。当在进加锁的时候会执行monitorenter指令,执行该指令可以获取对象的monitor。同时在执行Lock.wait()的时候也必须持有monitor对象。

    在多核环境下,多个线程有可能同时执行monitorenter指令,并获取lock对象关联的monitor,但只有一个线程可以和monitor建立关联,这个线程执行到wait方法时,wait方法会将当前线程放入wait set,使其进行等待直到被唤醒,并放弃lock对象上的所有同步声明,意味着该线程释放了锁,其他线程可以重新执行加锁操作,notify方法会选择wait set中任意一个线程进行唤醒,notifyAll方法会唤醒monitor的wait set中所有线程。执行完notify方法并不会立马唤醒等待线程。那么wait具体是怎么实现的呢?

    首先在HotSpot虚拟机中,monitor采用ObjectMonitor实现,每个线程都具有两个队列,分别为free和used,用来存放ObjectMonitor。如果当前free列表为空,线程将向全局global list请求分配ObjectMonitor。

    ObjectMonitor对象中有两个队列,都用来保存ObjectWaiter对象,分别是_WaitSet 和 _EntrySet。_owner用来指向获得ObjectMonitor对象的线程

    ObjectWaiter对象是双向链表结构,保存了_thread(当前线程)以及当前的状态TState等数据, 每个等待锁的线程都会被封装成ObjectWaiter对象。

   

    _WaitSet :处于wait状态的线程,会被加入到wait set;

    _EntrySett:处于等待锁block状态的线程,会被加入到entry set;

    wait方法实现:

    lock.wait()方法最终通过ObjectMonitor的 wait(jlong millis, bool interruptable, TRAPS)实现

    1、将当前线程封装成ObjectWaiter对象node

    2、通过ObjectMonitor::AddWaiter方法将node添加到_WaitSet列表中

    3、通过ObjectMonitor::exit方法释放当前的ObjectMonitor对象,这样其它竞争线程就可以获取该ObjectMonitor对象

    4、最终底层的park方法会挂起线程

    ObjectSynchorizer::wait方法通过Object对象找到ObjectMonitor对象来调用方法 ObjectMonitor::wait(),通过调用ObjectMonitor::AddWaiter()可以把新建的ObjectWaiter对象,放入到_WaitSet队列的末尾,然后在ObjectMonitor::exit释放锁,接着通过执行thread_ParkEvent->park来挂起线程,也就是进行wait。

 

 

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值