源碼解析-觸發批量撤銷或批量重偏向的條件

JVM 基於一種啓發式的做法判斷是否應該觸發批量撤銷或批量重偏向。

依賴三個閾值作出判斷:

# 批量重偏向閾值
-XX:BiasedLockingBulkRebiasThreshold=20
# 重置計數的延遲時間
-XX:BiasedLockingDecayTime=25000
# 批量撤銷閾值
-XX:BiasedLockingBulkRevokeThreshold=40

啓發式的判斷源碼如下:

static HeuristicsResult update_heuristics(oop o, bool allow_rebias) {
  markOop mark = o->mark();
  // 如果不是偏向模式直接返回
  if (!mark->has_bias_pattern()) {
    return HR_NOT_BIASED;
  }
 
  // 獲取鎖對象的類元數據
  Klass* k = o->klass();
  // 當前時間
  jlong cur_time = os::javaTimeMillis();
  // 該類上一次批量重偏向的時間
  jlong last_bulk_revocation_time = k->last_biased_lock_bulk_revocation_time();
  // 該類單個偏向撤銷的計數
  int revocation_count = k->biased_lock_revocation_count();

  // 按默認參數來說:
  // 如果撤銷計數大於等於 20,且小於 40,
  // 且距上次批量撤銷的時間大於等於 25 秒,就會重置計數。
  if ((revocation_count >= BiasedLockingBulkRebiasThreshold) &&
      (revocation_count <  BiasedLockingBulkRevokeThreshold) &&
      (last_bulk_revocation_time != 0) &&
      (cur_time - last_bulk_revocation_time >= BiasedLockingDecayTime)) {
    // This is the first revocation we've seen in a while of an
    // object of this type since the last time we performed a bulk
    // rebiasing operation. The application is allocating objects in
    // bulk which are biased toward a thread and then handing them
    // off to another thread. We can cope with this allocation
    // pattern via the bulk rebiasing mechanism so we reset the
    // klass's revocation count rather than allow it to increase
    // monotonically. If we see the need to perform another bulk
    // rebias operation later, we will, and if subsequently we see
    // many more revocation operations in a short period of time we
    // will completely disable biasing for this type.
    k->set_biased_lock_revocation_count(0);
    revocation_count = 0;
  }

  if (revocation_count <= BiasedLockingBulkRevokeThreshold) {
    // 自增計數
    revocation_count = k->atomic_incr_biased_lock_revocation_count();
  }
  // 此時,如果達到批量撤銷閾值,則進行批量撤銷。
  if (revocation_count == BiasedLockingBulkRevokeThreshold) {
    return HR_BULK_REVOKE;
  }
  // 此時,如果達到批量重偏向閾值,則進行批量重偏向。
  if (revocation_count == BiasedLockingBulkRebiasThreshold) {
    return HR_BULK_REBIAS;
  }
  // 否則,僅進行單個對象的撤銷偏向
  return HR_SINGLE_REVOKE;
}

簡單總結,對於一個類,按默認參數來說:
單個偏向撤銷的計數達到 20,就會進行批量重偏向。
距上次批量重偏向 25 秒內,計數達到 40,就會發生批量撤銷。

每隔 (>=) 25 秒,會重置在 [20, 40) 內的計數,這意味着可以發生多次批量重偏向。

注意:對於一個類來說,批量撤銷只能發生一次,因爲批量撤銷後,該類禁用了可偏向屬性,後面該類的對象都是不可偏向的,包括新創建的對象。

源碼鏈接:http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/file/9ce27f0a4683/src/share/vm/runtime/biasedLocking.cpp#l268

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章