Object中notify方法

    Object.java类中notify调用的是share/vm/prims/jvm.cpp中的JVM_MonitorNotify。

    void JVM_MonitorNotify(JNIEnv* env, jobject handle)

    {

             Handle obj(THREAD, JNIHandles::resolve_non_null(handle));

             ObjectSynchronizer::notify(obj, CHECK);

    }

    看看ObjectSynchronizer::notify方法

    void ObjectSynchronizer::notify(Handle obj, TRAPS)

    {

             ObjectSynchronizer::inflate(THREAD, obj())->notify(THREAD);

    }

    上面的inflate获得一个ObjectMonitor,看看它的具体实现

    void ObjectMonitor::notify(TRAPS)

   {

             if (_WaitSet == NULL) { //没有等待的线程,直接返回
                    return ;
             }

             Thread::SpinAcquire (&_WaitSetLock, "WaitSet - notify") ; //进入同步区域

             ObjectWaiter * iterator = DequeueWaiter() ; //获得一个等待对象

             if (iterator != NULL) {

                   ObjectWaiter * List = _EntryList ; //唤醒队列

                   //将唤醒的任务加入队列

                   if (List == NULL) {
                            iterator->_next = iterator->_prev = NULL ;
                           _EntryList = iterator ;
                   } else {
                           iterator->TState = ObjectWaiter::TS_CXQ ;
                           for (;;) {
                                     ObjectWaiter * Front = _cxq ;
                                     iterator->_next = Front ;
                                     if (Atomic::cmpxchg_ptr (iterator, &_cxq, Front) == Front) {
                                              break ;
                                     }
                            }
                   }

             }

             iterator->wait_reenter_begin(this);

             Thread::SpinRelease (&_WaitSetLock) ; //离开同步区域

             ...........

    }

    在上面的代码中,只看到了将当前的线程加入唤醒队列的操作,但在wait方法中执行了park()操作,那是执行操作系统的等待方法。上面的步骤显然不能直接唤醒线程运行,那这线程是如何真正运行的呢?

    我们知道wait和notify操作是在一个同步块内执行的,如果不在同步块内,会报IllegalMonitorStateException(非法监视器状态违例),真正唤醒的动作是在离开同步块时候,也就是monitorexit操作。

    好,我们再看看monitorexit的执行代码,看看是否正确,看看InterpreterRuntime::monitorexit代码

    void InterpreterRuntime::monitorexit(JavaThread* thread, BasicObjectLock* elem)

    {

             Handle h_obj(thread, elem->obj());

             ObjectSynchronizer::slow_exit(h_obj(), elem->lock(), thread);

    }

    跟踪进去,调用的是

    void  ObjectMonitor::exit

    {

             ...........

             w = _EntryList  ;
              if (w != NULL) {
                       ExitEpilog (Self, w) ;
                       return ;
              }

    }

    void ObjectMonitor::ExitEpilog (Thread * Self, ObjectWaiter * Wakee) {

              ParkEvent * Trigger = Wakee->_event ;

              .............

              Trigger->unpark() ; //通过操作系统提供的方法,真正唤醒线程

    }

    在上面可以证实是在监视器退去时候真正唤醒线程,同时也就明白了wait和notify 必须在synchronized块里面调用的原因,再回顾上篇wait代码中,也就理解了wait方法内必须执行退出监视器的原因。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值