• Java锁膨胀过程中的解惑:1.单线程不一定能获取偏向锁 ; 2.安全点重偏向不能直接占有仍有效偏向锁


    1.偏向锁的获取逻辑主要在汇编实现的  biased_locking_enter 方法中

    请求线程进入这个方法之后,会直接判断锁依赖对象的对象头是否有 偏向锁 成分(101是偏向锁成分)。

    如果没有,直接跳出,退出后直接尝试把自己栈上的BiasLock 地址写入对象头,写入成功的前提是锁依赖对象没加锁(001是没加锁)

    这样的话,岂不是所有未加锁对象,进入biased_locking_enter都会退出,直接设置轻量级锁成功?

    那么开启轻量级锁有什么用呢?

    问题在于,如果锁依赖对象的 Klass 的 prototype_header 中的 后几位是 101 ,也就是偏向锁成分。

    那么这个 Klass 的对象在创建的时候,都会直接把后几位设置成 101,但是没有写入 JavaThread* ,也就是匿名偏向锁(anonymous bias_lock)

    所以会在 biased_locking_enter  获得偏向锁成功。

    2.在 revoke_and_rebais 的最后,当 撤销偏向锁到达了一定频率,则会触发 请求线程使用 VM_Thread::execute 提交 VM_BulkRevokeBias 这个 operation 给VM_Thread 执行

    需要注意的是 VM_BulkRevokeBias 这个 Operation 是直接继承自 VM_Operation 的,调用evaluate_concurrently时

    默认使用VM_Operation的虚函数,默认返回 false,也就是 VM_Thread::execute 提交 Operation 请求以后会阻塞在提交点。

    VM_BulkRevokeBias 会在安全点(所有Operation都是在安全点执行的)调用bulk_revoke_or_rebias_at_safepoint

    这个函数 和 revoke_and_rebias 是膨胀过程中 唯二能返回 BIAS_REVOKED_AND_REBIASED 状态的函数

    返回这个状态表示锁依赖对象的对象头中的 JavaThread* 被置为当前线程的 JavaThread* 了。也就是当前线程获取偏向锁成功。也就是重偏向成功。

    但是有一个疑问,在函数的末尾貌似没有判断 对象头的 epoch 是否有效,直接就把自己的JavaThread*写进去了,我很是不解。

    虽然末尾要在  bulk_rebias 为 true ,attempt_rebias_of_object 都为 true 才会执行。

    但是 bulk_rebias 在 update_heuristics 调用较为频繁(revoke_and_rebias较为频繁,也就是偏向锁撤销较为频繁)的时候会 就会为true

    attempt_rebias_of_object 在 faster_enter 处被决定,通过 synchronized 进入 faster_enter 时,会是 true

    所以这两个值不难成立,为什么就能直接获得偏向锁呢?现在的线程可还在synchronized块里。

    但是实际上,我忽略了 bulk_rebias 为 true,会进入的分支里 ,会调用 revoke_bias。

    revoke_bias 在偏向锁被其他线程占有的时候,会直接把偏向锁膨胀成轻量级锁。

    这样的话,对象头的 偏向成分就会消失(101是偏向成分,bias_pattern),这样的话,末尾的 o->mark()->has_bias_pattern()

    就不会成立。

    static BiasedLocking::Condition bulk_revoke_or_rebias_at_safepoint(oop o,
                                                                       bool bulk_rebias,
                                                                       bool attempt_rebias_of_object,
                                                                       JavaThread* requesting_thread) {
    
      jlong cur_time = os::javaTimeMillis();
      o->blueprint()->set_last_biased_lock_bulk_revocation_time(cur_time);
    
      klassOop k_o = o->klass();
      Klass* klass = Klass::cast(k_o);
    
      if (bulk_rebias) {
        if (klass->prototype_header()->has_bias_pattern()) {
          int prev_epoch = klass->prototype_header()->bias_epoch();
          klass->set_prototype_header(klass->prototype_header()->incr_bias_epoch());
          int cur_epoch = klass->prototype_header()->bias_epoch();

    for (JavaThread* thr = Threads::first(); thr != NULL; thr = thr->next()) { GrowableArray<MonitorInfo*>* cached_monitor_info = get_or_compute_monitor_info(thr); for (int i = 0; i < cached_monitor_info->length(); i++) { MonitorInfo* mon_info = cached_monitor_info->at(i); oop owner = mon_info->owner(); markOop mark = owner->mark(); if ((owner->klass() == k_o) && mark->has_bias_pattern()) { assert(mark->bias_epoch() == prev_epoch || mark->bias_epoch() == cur_epoch, "error in bias epoch adjustment"); owner->set_mark(mark->set_bias_epoch(cur_epoch)); } } } }   // 被忽略的分支 revoke_bias(o, attempt_rebias_of_object && klass->prototype_header()->has_bias_pattern(), true, requesting_thread); } else { klass->set_prototype_header(markOopDesc::prototype()); for (JavaThread* thr = Threads::first(); thr != NULL; thr = thr->next()) { GrowableArray<MonitorInfo*>* cached_monitor_info = get_or_compute_monitor_info(thr); for (int i = 0; i < cached_monitor_info->length(); i++) { MonitorInfo* mon_info = cached_monitor_info->at(i); oop owner = mon_info->owner(); markOop mark = owner->mark(); if ((owner->klass() == k_o) && mark->has_bias_pattern()) { revoke_bias(owner, false, true, requesting_thread); } } } revoke_bias(o, false, true, requesting_thread); } BiasedLocking::Condition status_code = BiasedLocking::BIAS_REVOKED;  //末尾 bulk_rebias 为 true ,attempt_rebias_of_object 都为 true 才会执行 if (attempt_rebias_of_object && o->mark()->has_bias_pattern() && klass->prototype_header()->has_bias_pattern()) { markOop new_mark = markOopDesc::encode(requesting_thread, o->mark()->age(), klass->prototype_header()->bias_epoch()); o->set_mark(new_mark); status_code = BiasedLocking::BIAS_REVOKED_AND_REBIASED; }return status_code; }
  • 相关阅读:
    instanceof操作符判断对象类型
    继承
    题解 P3943 星空
    NOIP 模拟 10 考试总结
    题解 P3942 将军令
    题解 P3941 入阵曲
    题解 P3191 [HNOI2007]紧急疏散EVACUATE
    NOIP 模拟 9 考试总结
    NOIP 模拟 9 分组
    NOIP 模拟 9 数颜色
  • 原文地址:https://www.cnblogs.com/lqlqlq/p/13933868.html
Copyright © 2020-2023  润新知