达芬奇密码

除了技术,无它

439篇博客

Java Synchronized JVM实现分析(下篇)

达芬奇密码2018-08-17 15:16
轻量级锁
void ObjectSynchronizer::slow_enter(Handle obj, BasicLock* lock, TRAPS) {
  //获取对象的markword  
  markOop mark = obj->mark();
  assert(!mark->has_bias_pattern(), "should not see bias pattern here");
  //如果当前对象没有锁
  if (mark->is_neutral()) {
     //复制markword到栈 
    lock->set_displaced_header(mark);
    //如果CAS更新指向栈中的指针成功则释放栈锁,并返回
    if (mark == (markOop) Atomic::cmpxchg_ptr(lock, obj()->mark_addr(), mark)) {
      TEVENT (slow_enter: release stacklock) ;
      return ;
    }
    
  } else 
  if (mark->has_locker() && THREAD->is_lock_owned((address)mark->locker())) {//如果重入
    assert(lock != mark->locker(), "must not re-lock the same lock");
    assert(lock != (BasicLock*)obj->mark(), "don't relock with same BasicLock");
    lock->set_displaced_header(NULL);
    return;
  }
  
  lock->set_displaced_header(markOopDesc::unused_mark());
  //锁膨胀
  ObjectSynchronizer::inflate(THREAD, obj())->enter(THREAD);  //enter方法很关键
}
重量级锁
 ObjectMonitor * ATTR ObjectSynchronizer::inflate (Thread * Self, oop object) {
  
  assert (Universe::verify_in_progress() ||
          !SafepointSynchronize::is_at_safepoint(), "invariant") ;
      //自旋
  for (;;) {
      const markOop mark = object->mark() ;
      assert (!mark->has_bias_pattern(), "invariant") ;


      // 如果已经膨胀为重量级锁则直接返回
      if (mark->has_monitor()) {
         //获取对象的监视器锁
          ObjectMonitor * inf = mark->monitor() ;
          assert (inf->header()->is_neutral(), "invariant");
          assert (inf->object() == object, "invariant") ;
          assert (ObjectSynchronizer::verify_objmon_isinpool(inf), "monitor is invalid");
          return inf ;
      }

     
      //膨胀等待,其它线程正在从轻量级锁膨胀到重量级锁
      if (mark == markOopDesc::INFLATING()) {
         TEVENT (Inflate: spin while INFLATING) ;
         ReadStableMark(object) ;
         continue ;
      }

      
      //存在轻量级锁
      if (mark->has_locker()) {
          //获取可用监视器锁
          ObjectMonitor * m = omAlloc (Self) ;
         //初始化监视器锁
          m->Recycle();
          m->_Responsible  = NULL ;
          m->OwnerIsThread = 0 ;
          m->_recursions   = 0 ;
          m->_SpinDuration = ObjectMonitor::Knob_SpinLimit ;   // Consider: maintain by type/class

          //CAS更新状态为膨胀中
          markOop cmp = (markOop) Atomic::cmpxchg_ptr (markOopDesc::INFLATING(), object->mark_addr(), mark) ;
          //CAS更新失败
          if (cmp != mark) {
             omRelease (Self, m, true) ;
             continue ;       // Interference -- just retry
          }
          //已经成功更新了markword状态为膨胀中,它是锁状态更新为0的唯一途径,只有成功更新状态的单线程可以进行锁膨胀。
          
          //获取栈中的markword
          markOop dmw = mark->displaced_mark_helper() ;
          assert (dmw->is_neutral(), "invariant") ;

          //将监视器字段设置为适当的值
          m->set_header(dmw) ;

          
          //设置拥有锁的线程
          m->set_owner(mark->locker());
          //设置监视器的对象
          m->set_object(object);
          
          guarantee (object->mark() == markOopDesc::INFLATING(), "invariant") ;
          object->release_set_mark(markOopDesc::encode(m));

          if (ObjectMonitor::_sync_Inflations != NULL) ObjectMonitor::_sync_Inflations->inc() ;
          TEVENT(Inflate: overwrite stacklock) ;
          if (TraceMonitorInflation) {
            if (object->is_instance()) {
              ResourceMark rm;
              tty->print_cr("Inflating object " INTPTR_FORMAT " , mark " INTPTR_FORMAT " , type %s",
                (void *) object, (intptr_t) object->mark(),
                object->klass()->external_name());
            }
          }
          return m ;
      }

        
      // 无锁场景
      assert (mark->is_neutral(), "invariant");
      //分配一个有效对象监视器
      ObjectMonitor * m = omAlloc (Self) ;
      //重置监视器
      m->Recycle();
      m->set_header(mark);
      m->set_owner(NULL);
      m->set_object(object);
      m->OwnerIsThread = 1 ;
      m->_recursions   = 0 ;
      m->_Responsible  = NULL ;
      m->_SpinDuration = ObjectMonitor::Knob_SpinLimit ;       

      if (Atomic::cmpxchg_ptr (markOopDesc::encode(m), object->mark_addr(), mark) != mark) {
          m->set_object (NULL) ;
          m->set_owner  (NULL) ;
          m->OwnerIsThread = 0 ;
          m->Recycle() ;
          omRelease (Self, m, true) ;
          m = NULL ;
          continue ;
        
      }

     
      if (ObjectMonitor::_sync_Inflations != NULL) ObjectMonitor::_sync_Inflations->inc() ;
      TEVENT(Inflate: overwrite neutral) ;
      if (TraceMonitorInflation) {
        if (object->is_instance()) {
          ResourceMark rm;
          tty->print_cr("Inflating object " INTPTR_FORMAT " , mark " INTPTR_FORMAT " , type %s",
            (void *) object, (intptr_t) object->mark(),
            object->klass()->external_name());
        }
      }
      return m ;
  }
}

   上面代码中只看到了获取ObjectMonitor对象,通过enter方法获取了锁
  •    通过CAS尝试把monitor的_owner字段设置为当前线程;
  •    如果设置之前的_owner指向当前线程,说明当前线程再次进入monitor,即重入锁,执行_recursions ++ ,记录重入的次数;
  •    如果前线程是第一次进入该monitor,设置_recursions为1,_owner为当前线程,该线程成功获得锁并返回;
  •     如果获取锁失败,则等待锁的释放
Thread * const Self = THREAD ;
  void * cur ;
  //如果当前监视器锁没有被占用,通过CAS将owner更新为当前线程
  cur = Atomic::cmpxchg_ptr (Self, &_owner, NULL) ;
  //如果更新成功则返回
  if (cur == NULL) {
     // Either ASSERT _recursions == 0 or explicitly set _recursions = 0.
     assert (_recursions == 0   , "invariant") ;
     assert (_owner      == Self, "invariant") ;
     // CONSIDER: set or assert OwnerIsThread == 1
     return ;
  }
  //如果重入,则_recursions自增
  if (cur == Self) {
     _recursions ++ ;
     return ;
  }
  //获取监视器锁成功,将_recursions设置为1,_owner设置为当前线程
  if (Self->is_lock_owned ((address)cur)) {
    assert (_recursions == 0, "internal state error");
    _recursions = 1 ;
    _owner = Self ;
    OwnerIsThread = 1 ;
    return ;
  }

  //创建ObjectWaiter
    ObjectWaiter node(Self) ;
    Self->_ParkEvent->reset() ;
    node._prev   = (ObjectWaiter *) 0xBAD ;
    node.TState  = ObjectWaiter::TS_CXQ ;

    //将当前线程添加到_cxq加入到对头
    ObjectWaiter * nxt ;
    for (;;) {
        node._next = nxt = _cxq ;
        if (Atomic::cmpxchg_ptr (&node, &_cxq, nxt) == nxt) break ;
        //再次尝试获取锁
        if (TryLock (Self) > 0) {
            return ;
        }
    }


    if ((SyncFlags & 16) == 0 && nxt == NULL && _EntryList == NULL) {

        Atomic::cmpxchg_ptr (Self, &_Responsible, NULL) ;
    }



    TEVENT (Inflated enter - Contention) ;
    int nWakeups = 0 ;
    int RecheckInterval = 1 ;

for (;;) {

    //尝试获取锁

        if (TryLock (Self) > 0) break ;

        assert (_owner != Self, "invariant") ;

        if ((SyncFlags & 2) && _Responsible == NULL) {

           Atomic::cmpxchg_ptr (Self, &_Responsible, NULL) ;

        }

        // 如果指定时间则挂起一段时间

        if (_Responsible == Self || (SyncFlags & 1)) {

            TEVENT (Inflated enter - park TIMED) ;

            Self->_ParkEvent->park ((jlong) RecheckInterval) ;

            // Increase the RecheckInterval, but clamp the value.

            RecheckInterval *= 8 ;

            if (RecheckInterval > 1000) RecheckInterval = 1000 ;

        } else {//否则只能等待其它事件唤醒

            TEVENT (Inflated enter - park UNTIMED) ;

            Self->_ParkEvent->park() ;

        }

        //线程唤醒后再次尝试获取锁,如果查工获取锁结束阻塞

        if (TryLock(Self) > 0) break ;

 ObjectMonitor的注释:


 The ObjectMonitor class implements the heavyweight version of a

 JavaMonitor. The lightweight BasicLock/stack lock version has been

 inflated into an ObjectMonitor. This inflation is typically due to

 contention or use of Object.wait().


网易云新用户大礼包:https://www.163yun.com/gift

本文来自网易实践者社区,经作者张伟授权发布。