【Java核心-进阶】synchronized 底层实现

本文深入探讨了Java中synchronized关键字的底层实现机制,包括偏斜锁、轻量级锁和重量级锁的工作原理,以及锁升级和降级的过程。

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

synchronized 底层实现

  • synchronized 代码块的底层是通过一对指令 monitorenter 和 monitorexit 配合实现。
  • Java 6之前,Monitor依靠操作系统内部的互斥锁实现。这会涉及用户态和内核态的转换,所以是重量级操作。
  • 新的 JDK 提供了三种不同的实现:
    • 偏斜锁(Biased Locking):
      • JVM 利用 CAS 操作(compare and swap)标记同步对象(Mark Word部分)当前所偏向线程的ID,不涉及互斥,以此降低无竞争时的开销。
      • 这个设计基于假设:大部分对象在其生命周期中只会被一个线程锁定。
      • 可在 JVM 启动时指定参数 “-XX:+UseBiasedLocking” 启用偏斜锁;“-XX:-UseBiasedLocking” 禁用偏斜锁
    • 轻量级锁
      • 轻量级锁的获取也是通过 CAS 操作标记同步对象的Mark Word部分来获取
    • 重量级锁

 

锁的升级、降级

JVM 会根据检测到的竞争状况的不同,优化 synchronized 的运行机制,自动切换到合适的锁实现。

锁的升级

  • 没有竞争时,默认使用偏斜锁
    • 前提是已启用偏斜锁。如果偏斜锁被禁用,将尝试获取轻量级锁
  • 当某线程试图锁定已偏斜到其它线程的对象时,JVM 会撤销偏斜锁,并切换为轻量级锁
    • 注:撤销偏斜锁操作是比较重的行为
  • 如果获取轻量级锁失败,则会升级为重量级锁

锁的降级

当 JVM 进入安全点时,会检查是否有闲置的 Monitor;如果有,会尝试对其进行降级

  • 安全点:HotSpot JVM 处于 Stop-the-World 暂停(传说中的 STW)

 

部分源码

if (UseBiasedLocking) {
    // Retry fast entry if bias is revoked to avoid unnecessary inflation
    ObjectSynchronizer::fast_enter(h_obj, lock, true, CHECK);
} else {
    ObjectSynchronizer::slow_enter(h_obj, lock, CHECK);
}
 
void ObjectSynchronizer::fast_enter(Handle obj, BasicLock* lock, bool attempt_rebias, TRAPS) {
    if (UseBiasedLocking) {
        if (!SafepointSynchronize::is_at_safepoint()) {
            BiasedLocking::Condition cond = BiasedLocking::revoke_and_rebias(obj, attempt_rebias, THREAD);
            if (cond == BiasedLocking::BIAS_REVOKED_AND_REBIASED) {
                return;
            }
        } else {
            assert(!attempt_rebias, "can not rebias toward VM thread");
            BiasedLocking::revoke_at_safepoint(obj);
        }
        assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
    }

    slow_enter (obj, lock, THREAD) ;
}
 

注:代码中的“Atomic::cmpxchg_ptr”就是传说中的 CAS(compare and swap)

void ObjectSynchronizer::slow_enter(Handle obj, BasicLock* lock, TRAPS) {
    markOop mark = obj->mark();
    assert(!mark->has_bias_pattern(), "should not see bias pattern here");

    if (mark->is_neutral()) {
        // Anticipate successful CAS -- the ST of the displaced mark must
        // be visible <= the ST performed by the CAS.
        lock->set_displaced_header(mark);
        if (mark == (markOop) Atomic::cmpxchg_ptr(lock, obj()->mark_addr(), mark)) {
            TEVENT (slow_enter: release stacklock) ;
            return ;
        }
    // Fall through to inflate() ...
    } 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;
    }

    #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、付费专栏及课程。

余额充值