1、enter()——重量级锁的竞争和锁重入处理
bool ObjectMonitor::enter(JavaThread* current) {
void* cur = try_set_owner_from(NULL, current);
if (cur == NULL) {
assert(_recursions == 0, "invariant");
return true;
}
if (cur == current) {
_recursions++;
return true;
}
if (current->is_lock_owned((address)cur)) {
assert(_recursions == 0, "internal state error");
_recursions = 1;
set_owner_from_BasicLock(cur, current);
return true;
}
assert(current->_Stalled == 0, "invariant");
current->_Stalled = intptr_t(this);
if (TrySpin(current) > 0) {
assert(owner_raw() == current, "must be current: owner=" INTPTR_FORMAT, p2i(owner_raw()));
assert(_recursions == 0, "must be 0: recursions=" INTX_FORMAT, _recursions);
assert(object()->mark() == markWord::encode(this),
"object mark must match encoded this: mark=" INTPTR_FORMAT
", encoded this=" INTPTR_FORMAT, object()->mark().value(),
markWord::encode(this).value());
current->_Stalled = 0;
return true;
}
2、自旋——TrySpin()
int ObjectMonitor::TrySpin(JavaThread* current) {
int ctr = Knob_FixedSpin;
if (ctr != 0) {
while (--ctr >= 0) {
if (TryLock(current) > 0) return 1;
SpinPause();
}
return 0;
}
for (ctr = Knob_PreSpin + 1; --ctr >= 0;) {
if (TryLock(current) > 0) {
int x = _SpinDuration;
if (x < Knob_SpinLimit) {
if (x < Knob_Poverty) x = Knob_Poverty;
_SpinDuration = x + Knob_BonusB;
}
return 1;
}
SpinPause();
}
ctr = _SpinDuration;
if (ctr <= 0) return 0;
if (NotRunnable(current, (JavaThread*) owner_raw())) {
return 0;
}
if (_succ == NULL) {
_succ = current;
}
Thread* prv = NULL;
while (--ctr >= 0) {
if ((ctr & 0xFF) == 0) {
if (SafepointMechanism::should_process(current)) {
goto Abort;
}
SpinPause();
}
JavaThread* ox = (JavaThread*) owner_raw();
if (ox == NULL) {
ox = (JavaThread*)try_set_owner_from(NULL, current);
if (ox == NULL) {
if (_succ == current) {
_succ = NULL;
}
int x = _SpinDuration;
if (x < Knob_SpinLimit) {
if (x < Knob_Poverty) x = Knob_Poverty;
_SpinDuration = x + Knob_Bonus;
}
return 1;
}
prv = ox;
goto Abort;
}
if (ox != prv && prv != NULL) {
goto Abort;
}
prv = ox;
if (NotRunnable(current, ox)) {
goto Abort;
}
if (_succ == NULL) {
_succ = current;
}
}
{
int x = _SpinDuration;
if (x > 0) {
x -= Knob_Penalty;
if (x < 0) x = 0;
_SpinDuration = x;
}
}
Abort:
if (_succ == current) {
_succ = NULL;
OrderAccess::fence();
if (TryLock(current) > 0) return 1;
}
return 0;
}
3、自旋之后
if (TrySpin(current) > 0) {
assert(owner_raw() == current, "must be current: owner=" INTPTR_FORMAT, p2i(owner_raw()));
assert(_recursions == 0, "must be 0: recursions=" INTX_FORMAT, _recursions);
assert(object()->mark() == markWord::encode(this),
"object mark must match encoded this: mark=" INTPTR_FORMAT
", encoded this=" INTPTR_FORMAT, object()->mark().value(),
markWord::encode(this).value());
current->_Stalled = 0;
return true;
}
for (;;) {
ExitOnSuspend eos(this);
{
ThreadBlockInVMPreprocess<ExitOnSuspend> tbivs(current, eos, true );
EnterI(current);
current->set_current_pending_monitor(NULL);
}
if (!eos.exited()) {
assert(owner_raw() == current, "invariant");
break;
}
}
}
add_to_contentions(-1);
assert(contentions() >= 0, "must not be negative: contentions=%d", contentions());
current->_Stalled = 0;
assert(_recursions == 0, "invariant");
assert(owner_raw() == current, "invariant");
assert(_succ != current, "invariant");
assert(object()->mark() == markWord::encode(this), "invariant");
DTRACE_MONITOR_PROBE(contended__entered, this, object(), current);
if (JvmtiExport::should_post_monitor_contended_entered()) {
JvmtiExport::post_monitor_contended_entered(current, this);
}
if (event.should_commit()) {
event.set_previousOwner(_previous_owner_tid);
event.commit();
}
OM_PERFDATA_OP(ContendedLockAttempts, inc());
return true;
}
4、enterI() —— 再自旋与cxq
- 先简单说一下park,直接看代码吧,应该很容易理解
public static void main(String[] args) {
Thread main = Thread.currentThread();
LockSupport.unpark(main);
LockSupport.park();
System.out.println("暂停了吗?");
}
public static void main(String[] args) {
Thread main = Thread.currentThread();
LockSupport.unpark(main);
LockSupport.park();
LockSupport.park();
System.out.println("暂停了吗?");
}
void ObjectMonitor::EnterI(JavaThread* current) {
assert(current->thread_state() == _thread_blocked, "invariant");
if (TryLock (current) > 0) {
assert(_succ != current, "invariant");
assert(owner_raw() == current, "invariant");
assert(_Responsible != current, "invariant");
return;
}
if (try_set_owner_from(DEFLATER_MARKER, current) == DEFLATER_MARKER) {
add_to_contentions(1);
assert(_succ != current, "invariant");
assert(_Responsible != current, "invariant");
return;
}
assert(InitDone, "Unexpectedly not initialized");
if (TrySpin(current) > 0) {
assert(owner_raw() == current, "invariant");
assert(_succ != current, "invariant");
assert(_Responsible != current, "invariant");
return;
}
assert(_succ != current, "invariant");
assert(owner_raw() != current, "invariant");
assert(_Responsible != current, "invariant");
ObjectWaiter node(current);
current->_ParkEvent->reset();
node._prev = (ObjectWaiter*) 0xBAD;
node.TState = ObjectWaiter::TS_CXQ;
ObjectWaiter* nxt;
for (;;) {
node._next = nxt = _cxq;
if (Atomic::cmpxchg(&_cxq, nxt, &node) == nxt)
break;
if (TryLock (current) > 0) {
assert(_succ != current, "invariant");
assert(owner_raw() == current, "invariant");
assert(_Responsible != current, "invariant");
return;
}
}
if (nxt == NULL && _EntryList == NULL) {
Atomic::replace_if_null(&_Responsible, current);
}
int nWakeups = 0;
int recheckInterval = 1;
for (;;) {
if (TryLock(current) > 0) break;
assert(owner_raw() != current, "invariant");
if (_Responsible == current) {
current->_ParkEvent->park((jlong) recheckInterval);
recheckInterval *= 8;
if (recheckInterval > MAX_RECHECK_INTERVAL) {
recheckInterval = MAX_RECHECK_INTERVAL;
}
} else {
current->_ParkEvent->park();
}
if (TryLock(current) > 0) break;
if (try_set_owner_from(DEFLATER_MARKER, current) == DEFLATER_MARKER) {
add_to_contentions(1);
break;
}
OM_PERFDATA_OP(FutileWakeups, inc());
++nWakeups;
if (TrySpin(current) > 0) break;
if (_succ == current) _succ = NULL;
OrderAccess::fence();
}
assert(owner_raw() == current, "invariant");
UnlinkAfterAcquire(current, &node);
if (_succ == current) _succ = NULL;
assert(_succ != current, "invariant");
if (_Responsible == current) {
_Responsible = NULL;
OrderAccess::fence();
}
return;
}
- 笔者已经越看越无语了,ReentrantLock真香.......不过到这里,经历了无数次自旋失败再重试,线程终于进入cxq后老老实实的park了