synchronized偏向锁、轻量锁、重量锁加锁原理

本文深入剖析了Java中synchronized的实现原理,包括无锁、偏向锁和轻量级锁的转换逻辑。详细解读了源码中的CAS操作和锁升级过程,阐述了JVM如何通过优化减少锁的开销,提升并发性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前提知识点:

无锁001

偏向锁101

轻量锁00

重量锁10

synchronized对应c++执行逻辑

源码

    case got_monitors: {
      // continue locking now that we have a monitor to use
      // we expect to find newly allocated monitor at the "top" of the monitor stack.
      oop lockee = STACK_OBJECT(-1);
      VERIFY_OOP(lockee);
      // derefing's lockee ought to provoke implicit null check
      // find a free monitor
      // 在线程栈中创建lock record
      BasicObjectLock* entry = (BasicObjectLock*) istate->stack_base();
      assert(entry->obj() == NULL, "Frame manager didn't allocate the monitor");
      // 获取锁对象
      entry->set_obj(lockee);
      bool success = false;
      uintptr_t epoch_mask_in_place = markWord::epoch_mask_in_place;

      markWord mark = lockee->mark();
      intptr_t hash = (intptr_t) markWord::no_hash;
      // implies UseBiasedLocking
      // JVM是否开启偏向模式
      if (mark.has_bias_pattern()) {
        // JVM开启偏向模式
        uintptr_t thread_ident;
        uintptr_t anticipated_bias_locking_value;
        thread_ident = (uintptr_t)istate->thread();
        anticipated_bias_locking_value =
          ((lockee->klass()->prototype_header().value() | thread_ident) ^ mark.value()) &
          ~(markWord::age_mask_in_place);
        //  偏向锁是否偏向自己
        if  (anticipated_bias_locking_value == 0) {
          // 偏向锁偏向自己,获取cpu执行
          // already biased towards this thread, nothing to do
          if (PrintBiasedLockingStatistics) {
            (* BiasedLocking::biased_lock_entry_count_addr())++;
          }
          success = true;
        } 
        //  偏向锁是否被禁用
        else if ((anticipated_bias_locking_value & markWord::biased_lock_mask_in_place) != 0) {
          // 偏向锁被禁用(偏向锁锁撤销达到40次+)
          // try revoke bias
          // 获取类中的不可的偏向锁001
          markWord header = lockee->klass()->prototype_header();
          if (hash != markWord::no_hash) {
            header = header.copy_set_hash(hash);
          }
          // cas 更新锁对象状态为无锁001,成功或者失败都走轻量锁模式
          if (lockee->cas_set_mark(header, mark) == mark) {
            if (PrintBiasedLockingStatistics) {
              (*BiasedLocking::revoked_lock_entry_count_addr())++;
            }
          }
        } 
       // 锁对象的epoch值是否过期(偏向锁撤销达到20次+)
       else if ((anticipated_bias_locking_value & epoch_mask_in_place) !=0) {
          // 过期,锁撤销大于20次,执行批量重偏向
          // new 偏向当前线程的mark word
          // try rebias
          markWord new_header( (intptr_t) lockee->klass()->prototype_header().value() | thread_ident);
          if (hash != markWord::no_hash) {
            new_header = new_header.copy_set_hash(hash);
          }
          // cas 更新锁对象为偏向当前线程的mark word
          if (lockee->cas_set_mark(new_header, mark) == mark) {
            if (PrintBiasedLockingStatistics) {
              (* BiasedLocking::rebiased_lock_entry_count_addr())++;
            }
          } else {
            // 执行锁撤销,轻量锁膨胀过程
            CALL_VM(InterpreterRuntime::monitorenter(THREAD, entry), handle_exception);
          }
          success = true;
        }
         // 匿名偏向锁,偏向其它线程偏向锁
         else {
          // try to bias towards thread in case object is anonymously biased
          // new 匿名偏向锁101
          markWord header(mark.value() & (markWord::biased_lock_mask_in_place |
                                          markWord::age_mask_in_place | epoch_mask_in_place));
          if (hash != markWord::no_hash) {
            header = header.copy_set_hash(hash);
          }
          markWord new_header(header.value() | thread_ident);
          // debugging hint
          DEBUG_ONLY(entry->lock()->set_displaced_header(markWord((uintptr_t) 0xdeaddead));)
           // 是否是匿名偏向锁加锁
          if (lockee->cas_set_mark(new_header, header) == header) {
            // 是匿名偏向锁加锁
            if (PrintBiasedLockingStatistics) {
              (* BiasedLocking::anonymously_biased_lock_entry_count_addr())++;
            }
          } else {
            // 是偏向其它线程偏向锁,执行锁撤销,轻量锁膨胀过程
            CALL_VM(InterpreterRuntime::monitorenter(THREAD, entry), handle_exception);
          }
          success = true;
        }
      }

      // traditional lightweight locking
      // 关闭偏向,偏向锁禁用
      if (!success) {
        // new 无锁001
        markWord displaced = lockee->mark().set_unlocked();
        entry->lock()->set_displaced_header(displaced);
        bool call_vm = UseHeavyMonitors;
         // cas 偏向锁的状态为无锁001
        if (call_vm || lockee->cas_set_mark(markWord::from_pointer(entry), displaced) != displaced) {
          // cas失败
          // 是否是重入锁
          // Is it simple recursive case?
          if (!call_vm && THREAD->is_lock_owned((address) displaced.clear_lock_bits().to_pointer())) {
            entry->lock()->set_displaced_header(markWord::from_pointer(NULL));
          } else {
            // 其它线程持有偏向锁,执行锁撤销,轻量锁膨胀过程
            CALL_VM(InterpreterRuntime::monitorenter(THREAD, entry), handle_exception);
          }
        }
      }
      // 获取cpu进行执行
      UPDATE_PC_AND_TOS(1, -1);
      goto run;
    }
    default: {
      fatal("Unexpected message from frame manager");
    }
  }

轻量锁加锁执行逻辑

源码

void ObjectSynchronizer::slow_enter(Handle obj, BasicLock* lock, TRAPS) {
  markOop mark = obj->mark();
  assert(!mark->has_bias_pattern(), "should not see bias pattern here");
   // 是否是无锁001,(锁撤销是否成功)(其它线程有无持有锁)
  if (mark->is_neutral()) {
    // 无锁001
    // Anticipate successful CAS -- the ST of the displaced mark must
    // be visible <= the ST performed by the CAS.
    lock->set_displaced_header(mark);
    // cas 修改锁对象mark word指向lock record
    if (mark == (markOop) Atomic::cmpxchg_ptr(lock, obj()->mark_addr(), mark)) {
      // 成功修改锁对象mark word指向lock record
      TEVENT (slow_enter: release stacklock) ;
      // 返回,获取cpu执行
      return ;
    }
    // Fall through to inflate() ...
  } else{
   // 有锁001
   // 是否是重入锁
  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;
  }

#if 0
  // The following optimization isn't particularly useful.
  if (mark->has_monitor() && mark->monitor()->is_entered(THREAD)) {
    lock->set_displaced_header (NULL) ;
    return ;
  }
#endif

  // The object header will never be displaced to this lock,
  // so it does not matter what the value is, except that it
  // must be non-zero to avoid looking like a re-entrant lock,
  // and must not look locked either.
  lock->set_displaced_header(markOopDesc::unused_mark());
  // 锁膨胀成重量锁
  ObjectSynchronizer::inflate(THREAD, obj())->enter(THREAD);
}
}

梳理的流程

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值