JDK18:Synchronizer的cpp源码分析(一)——轻量级锁加锁&膨胀&释放

106 阅读5分钟

作者cpp水平有限,所以阅读源码不会很深入

jdk版本: jdk18-27

该版本已删除偏向级锁流程,在jdk22中轻量级锁也删除,变为fast_lock,还引入了lock_stack

源码目录: hotspot/share/runtime/synchornized

加锁流程

//BasicLock 轻量级锁
void ObjectSynchronizer::enter(Handle obj, BasicLock* lock, JavaThread* current) {
  if (obj->klass()->is_value_based()) {
    handle_sync_on_value_based_class(obj, current);
  }

  if (!useHeavyMonitors()) { //是否只使用重量级锁(可通过jvm参数控制)
    markWord mark = obj->mark(); //拿到《要加锁的对象》的Markword
    if (mark.is_neutral()) {  //判断是否处于无锁状态(根据后两位标志位判断)
      lock->set_displaced_header(mark); //将markword放到轻量级锁中(解锁时从里面取出,还原markword)
      //from_pointer(lock) 获取轻量级锁的地址指针
      //cas_set_mark()     将轻量级锁的地址指针放入《加锁的对象》的markword中
      //判断是否cas成功
      if (mark == obj()->cas_set_mark(markWord::from_pointer(lock), mark)) {
        //如果无竞争,设置成功,返回
        return;
      }
      //获取失败
      // Fall through to inflate() ...
    } else if (mark.has_locker() &&  //如果已经加轻量级锁了 并且当前线程是锁的持有者,走锁重入流程
               current->is_lock_owned((address)mark.locker())) {
      assert(lock != mark.locker(), "must not re-lock the same lock");
      assert(lock != (BasicLock*)obj->mark().value(), "don't relock with same BasicLock");
      lock->set_displaced_header(markWord::from_pointer(NULL)); //锁重入时,锁对象不需要储存原始的markword信息,只放入一个空地址指针
      return; //锁重入加锁流程结束
    }
    lock->set_displaced_header(markWord::unused_mark()); //设置没有使用的状态 不重要
  } else if (VerifyHeavyMonitors) {
    guarantee(!obj->mark().has_locker(), "must not be stack-locked");
  }
  while (true) {
    //进入锁膨胀流程,加重量级锁     参数:要加锁的线程、加锁的对象
    ObjectMonitor* monitor = inflate(current, obj(), inflate_cause_monitor_enter);
    if (monitor->enter(current)) {
      return;
    }
  }
}

锁膨胀流程

ObjectMonitor* ObjectSynchronizer::inflate(Thread* current, oop object,
                                           const InflateCause cause) {
  EventJavaMonitorInflate event;

  //循环
  for (;;) {
    const markWord mark = object->mark_acquire(); //获取《加锁的对象》的markword

    // 几种膨胀状态,重要
    // The mark can be in one of the following states:
    // *  Inflated     - just return  膨胀完成
    // *  Stack-locked - coerce it to inflated  从轻量级锁开始膨胀
    // *  INFLATING    - busy wait for conversion to complete  膨胀中
    // *  Neutral      - aggressively inflate the object.   从无锁状态开始膨胀

    // CASE: inflated
    if (mark.has_monitor()) { //判断是否膨胀完毕(检查锁标志位即可)
      ObjectMonitor* inf = mark.monitor();
      markWord dmw = inf->header();
      assert(dmw.is_neutral(), "invariant: header=" INTPTR_FORMAT, dmw.value());
      return inf; //返回重量级锁对象
    }

    if (mark == markWord::INFLATING()) {  //膨胀中 (线程发生竞争时,保证仅有一个线程膨胀成功)
      read_stable_mark(object); //等待一会,等膨胀的那个线程膨胀完
      continue;
    }

    LogStreamHandle(Trace, monitorinflation) lsh;

    //从轻量级锁开始膨胀为重量级锁
    if (mark.has_locker()) {    //是否为轻量级锁 如果是则发生竞争 准备膨胀
      ObjectMonitor* m = new ObjectMonitor(object);//创建一个重量级锁对象

      //仅有一个线程能成功,成功的线程执行具体的膨胀流程;失败的线程循环等待
      //markword信息还会有一些中间态,比如膨胀中的信息也会放入markword
      markWord cmp = object->cas_set_mark(markWord::INFLATING(), mark); //将markword信息设置为膨胀中
      if (cmp != mark) { //cas失败(膨胀失败,发生竞争且没抢过)
        delete m;        //删除重量级锁对象
        continue;       // Interference -- just retry
      }
      
      markWord dmw = mark.displaced_mark_helper();  //获取原始markword,准备存入重量级锁
      
      assert(dmw.is_neutral(), "invariant: header=" INTPTR_FORMAT, dmw.value());
      
      m->set_header(dmw); //原始markword存入重量级锁

      m->set_owner_from(NULL, mark.locker()); //设置重量级锁持锁线程,设置的是轻量级锁的持锁线程!

      guarantee(object->mark() == markWord::INFLATING(), "invariant");
      
      object->release_set_mark(markWord::encode(m)); //《加锁的对象》后两位改成02,设置为存放重量级锁的地址指针

      _in_use_list.add(m);

      OM_PERFDATA_OP(Inflations, inc());
      if (log_is_enabled(Trace, monitorinflation)) {
        ResourceMark rm(current);
        lsh.print_cr("inflate(has_locker): object=" INTPTR_FORMAT ", mark="
                     INTPTR_FORMAT ", type='%s'", p2i(object),
                     object->mark().value(), object->klass()->external_name());
      }
      if (event.should_commit()) {
        post_monitor_inflate_event(&event, object, cause);
      }
      return m; //膨胀结束,返回重量级锁
    }

    //从无锁状态开始膨胀
    assert(mark.is_neutral(), "invariant: header=" INTPTR_FORMAT, mark.value());//检查是否无锁
    ObjectMonitor* m = new ObjectMonitor(object); //创建重量级锁
    m->set_header(mark); //直接将原始markword值放入重量级锁中(因为对象是无锁状态,markword是原始的)

    //将《加锁的对象》markword中设置重量级锁的地址
    if (object->cas_set_mark(markWord::encode(m), mark) != mark) {
      delete m; //加锁失败 删除重量级锁
      m = NULL;
      continue;
    }

    _in_use_list.add(m);

    OM_PERFDATA_OP(Inflations, inc());
    if (log_is_enabled(Trace, monitorinflation)) {
      ResourceMark rm(current);
      lsh.print_cr("inflate(neutral): object=" INTPTR_FORMAT ", mark="
                   INTPTR_FORMAT ", type='%s'", p2i(object),
                   object->mark().value(), object->klass()->external_name());
    }
    if (event.should_commit()) {
      post_monitor_inflate_event(&event, object, cause);
    }
    return m; //返回Moniter对象
  }
}

释放流程

//加锁的对象   锁对象(锁本身)  操作的线程    
void ObjectSynchronizer::exit(oop object, BasicLock* lock, JavaThread* current) {
  if (!useHeavyMonitors()) {
    markWord mark = object->mark(); //拿到《加锁的对象》的markWord

    markWord dhw = lock->displaced_header(); //获取《锁对象》的对象头信息,如果发生锁重入拿的空header
    if (dhw.value() == 0) { //锁重入解锁,正常情况下return 解锁成功
#ifndef PRODUCT
      if (mark != markWord::INFLATING()) {
        assert(!mark.is_neutral(), "invariant");
        assert(!mark.has_locker() ||
        current->is_lock_owned((address)mark.locker()), "invariant");
        if (mark.has_monitor()) {
          ObjectMonitor* m = mark.monitor();
          assert(m->object()->mark() == mark, "invariant");
          assert(m->is_entered(current), "invariant");
        }
      }
#endif
      return;
    }

    // mark是《加锁的对象》的markword   from_pointer(lock)获取的是《锁对象》的指针
    // 如果相同,进入最外层轻量级锁解锁流程
    if (mark == markWord::from_pointer(lock)) {
      assert(dhw.is_neutral(), "invariant");
      //还原《加锁的对象》的markword,完成轻量级锁解锁
      //dhw作为《锁对象》,他的对象中存储的是《加锁的对象》的原始markword
      if (object->cas_set_mark(dhw, mark) == mark) {
        return;
      }
    }
  } else if (VerifyHeavyMonitors) {
    //重量级锁
    guarantee(!object->mark().has_locker(), "must not be stack-locked");
  }
  
  //轻量级锁解锁失败,膨胀为重量级锁
  ObjectMonitor* monitor = inflate(current, object, inflate_cause_vm_internal);
  //再进入重量级锁解锁流程
  monitor->exit(current);
}