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) 内的计数,这意味着可以发生多次批量重偏向。
注意:对于一个类来说,批量撤销只能发生一次,因为批量撤销后,该类禁用了可偏向属性,后面该类的对象都是不可偏向的,包括新创建的对象。
网友评论