java怎么撤销_Java偏向锁是如何撤销的?

BiasedLocking::Condition BiasedLocking::revoke_and_rebias(Handle obj, bool attempt_rebias, TRAPS) {

assert(!SafepointSynchronize::is_at_safepoint(), "must not be called while at safepoint");

// We can revoke the biases of anonymously-biased objects // efficiently enough that we should not cause these revocations to // update the heuristics because doing so may cause unwanted bulk // revocations (which are expensive) to occur. markOop mark = obj->mark();

if (mark->is_biased_anonymously() && !attempt_rebias) {

// We are probably trying to revoke the bias of this object due to // an identity hash code computation. Try to revoke the bias // without a safepoint. This is possible if we can successfully // compare-and-exchange an unbiased header into the mark word of // the object, meaning that no other thread has raced to acquire // the bias of the object. markOop biased_value = mark;

markOop unbiased_prototype = markOopDesc::prototype()->set_age(mark->age());

markOop res_mark = (markOop) Atomic::cmpxchg_ptr(unbiased_prototype, obj->mark_addr(), mark);

if (res_mark == biased_value) {

return BIAS_REVOKED;

}

} else if (mark->has_bias_pattern()) {

Klass* k = obj->klass();

markOop prototype_header = k->prototype_header();

if (!prototype_header->has_bias_pattern()) {

// This object has a stale bias from before the bulk revocation // for this data type occurred. It's pointless to update the // heuristics at this point so simply update the header with a // CAS. If we fail this race, the object's bias has been revoked // by another thread so we simply return and let the caller deal // with it. markOop biased_value = mark;

markOop res_mark = (markOop) Atomic::cmpxchg_ptr(prototype_header, obj->mark_addr(), mark);

assert(!(*(obj->mark_addr()))->has_bias_pattern(), "even if we raced, should still be revoked");

return BIAS_REVOKED;

} else if (prototype_header->bias_epoch() != mark->bias_epoch()) {

// The epoch of this biasing has expired indicating that the // object is effectively unbiased. Depending on whether we need // to rebias or revoke the bias of this object we can do it // efficiently enough with a CAS that we shouldn't update the // heuristics. This is normally done in the assembly code but we // can reach this point due to various points in the runtime // needing to revoke biases. if (attempt_rebias) {

assert(THREAD->is_Java_thread(), "");

markOop biased_value = mark;

markOop rebiased_prototype = markOopDesc::encode((JavaThread*) THREAD, mark->age(), prototype_header->bias_epoch());

markOop res_mark = (markOop) Atomic::cmpxchg_ptr(rebiased_prototype, obj->mark_addr(), mark);

if (res_mark == biased_value) {

return BIAS_REVOKED_AND_REBIASED;

}

} else {

markOop biased_value = mark;

markOop unbiased_prototype = markOopDesc::prototype()->set_age(mark->age());

markOop res_mark = (markOop) Atomic::cmpxchg_ptr(unbiased_prototype, obj->mark_addr(), mark);

if (res_mark == biased_value) {

return BIAS_REVOKED;

}

}

}

}

HeuristicsResult heuristics = update_heuristics(obj(), attempt_rebias);

if (heuristics == HR_NOT_BIASED) {

return NOT_BIASED;

} else if (heuristics == HR_SINGLE_REVOKE) {

Klass *k = obj->klass();

markOop prototype_header = k->prototype_header();

if (mark->biased_locker() == THREAD &&

prototype_header->bias_epoch() == mark->bias_epoch()) {

// A thread is trying to revoke the bias of an object biased // toward it, again likely due to an identity hash code // computation. We can again avoid a safepoint in this case // since we are only going to walk our own stack. There are no // races with revocations occurring in other threads because we // reach no safepoints in the revocation path. // Also check the epoch because even if threads match, another thread // can come in with a CAS to steal the bias of an object that has a // stale epoch. ResourceMark rm;

if (TraceBiasedLocking) {

tty->print_cr("Revoking bias by walking my own stack:");

}

BiasedLocking::Condition cond = revoke_bias(obj(), false, false, (JavaThread*) THREAD);

((JavaThread*) THREAD)->set_cached_monitor_info(NULL);

assert(cond == BIAS_REVOKED, "why not?");

return cond;

} else {

VM_RevokeBias revoke(&obj, (JavaThread*) THREAD);

VMThread::execute(&revoke);

return revoke.status_code();

}

}

assert((heuristics == HR_BULK_REVOKE) ||

(heuristics == HR_BULK_REBIAS), "?");

VM_BulkRevokeBias bulk_revoke(&obj, (JavaThread*) THREAD,

(heuristics == HR_BULK_REBIAS),

attempt_rebias);

VMThread::execute(&bulk_revoke);

return bulk_revoke.status_code();

}

static BiasedLocking::Condition revoke_bias(oop obj, bool allow_rebias, bool is_bulk, JavaThread* requesting_thread) {

markOop mark = obj->mark();

if (!mark->has_bias_pattern()) {

if (TraceBiasedLocking) {

ResourceMark rm;

tty->print_cr(" (Skipping revocation of object of type %s because it's no longer biased)",

obj->klass()->external_name());

}

return BiasedLocking::NOT_BIASED;

}

uint age = mark->age();

markOop biased_prototype = markOopDesc::biased_locking_prototype()->set_age(age);

markOop unbiased_prototype = markOopDesc::prototype()->set_age(age);

if (TraceBiasedLocking && (Verbose || !is_bulk)) {

ResourceMark rm;

tty->print_cr("Revoking bias of object " INTPTR_FORMAT " , mark " INTPTR_FORMAT " , type %s , prototype header " INTPTR_FORMAT " , allow rebias %d , requesting thread " INTPTR_FORMAT,

(void *)obj, (intptr_t) mark, obj->klass()->external_name(), (intptr_t) obj->klass()->prototype_header(), (allow_rebias ? 1 : 0), (intptr_t) requesting_thread);

}

JavaThread* biased_thread = mark->biased_locker();

if (biased_thread == NULL) {

// Object is anonymously biased. We can get here if, for // example, we revoke the bias due to an identity hash code // being computed for an object. if (!allow_rebias) {

obj->set_mark(unbiased_prototype);

}

if (TraceBiasedLocking && (Verbose || !is_bulk)) {

tty->print_cr(" Revoked bias of anonymously-biased object");

}

return BiasedLocking::BIAS_REVOKED;

}

// Handle case where the thread toward which the object was biased has exited bool thread_is_alive = false;

if (requesting_thread == biased_thread) {

thread_is_alive = true;

} else {

for (JavaThread* cur_thread = Threads::first(); cur_thread != NULL; cur_thread = cur_thread->next()) {

if (cur_thread == biased_thread) {

thread_is_alive = true;

break;

}

}

}

if (!thread_is_alive) {

if (allow_rebias) {

obj->set_mark(biased_prototype);

} else {

obj->set_mark(unbiased_prototype);

}

if (TraceBiasedLocking && (Verbose || !is_bulk)) {

tty->print_cr(" Revoked bias of object biased toward dead thread");

}

return BiasedLocking::BIAS_REVOKED;

}

// Thread owning bias is alive. // Check to see whether it currently owns the lock and, if so, // write down the needed displaced headers to the thread's stack. // Otherwise, restore the object's header either to the unlocked // or unbiased state. GrowableArray* cached_monitor_info = get_or_compute_monitor_info(biased_thread);

BasicLock* highest_lock = NULL;

for (int i = 0; i < cached_monitor_info->length(); i++) {

MonitorInfo* mon_info = cached_monitor_info->at(i);

if (mon_info->owner() == obj) {

if (TraceBiasedLocking && Verbose) {

tty->print_cr(" mon_info->owner (" PTR_FORMAT ") == obj (" PTR_FORMAT ")",

(void *) mon_info->owner(),

(void *) obj);

}

// Assume recursive case and fix up highest lock later markOop mark = markOopDesc::encode((BasicLock*) NULL);

highest_lock = mon_info->lock();

highest_lock->set_displaced_header(mark);

} else {

if (TraceBiasedLocking && Verbose) {

tty->print_cr(" mon_info->owner (" PTR_FORMAT ") != obj (" PTR_FORMAT ")",

(void *) mon_info->owner(),

(void *) obj);

}

}

}

if (highest_lock != NULL) {

// Fix up highest lock to contain displaced header and point // object at it highest_lock->set_displaced_header(unbiased_prototype);

// Reset object header to point to displaced mark obj->set_mark(markOopDesc::encode(highest_lock));

assert(!obj->mark()->has_bias_pattern(), "illegal mark state: stack lock used bias bit");

if (TraceBiasedLocking && (Verbose || !is_bulk)) {

tty->print_cr(" Revoked bias of currently-locked object");

}

} else {

if (TraceBiasedLocking && (Verbose || !is_bulk)) {

tty->print_cr(" Revoked bias of currently-unlocked object");

}

if (allow_rebias) {

obj->set_mark(biased_prototype);

} else {

// Store the unlocked value into the object's header. obj->set_mark(unbiased_prototype);

}

}

return BiasedLocking::BIAS_REVOKED;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值