目录
1、定义
2、TrySpin_VaryDuration
3、ObjectWaiter
4、EnterI
5、JavaThreadBlockedOnMonitorEnterState / OSThreadContendState / ThreadBlockInVM
6、enter
ObjectMonitor不仅是重量级锁的实现,还是Object的wait/notify/notifyAll方法的底层核心实现,本篇博客就详细探讨该类的实现。
ObjectMonitor的定义位于hotspot\src\share\vm\runtime\objectMonitor.hpp中,包含如下属性:
默认配置下自旋的次数是会自适应调整的,可以通过参数指定自旋固定的次数,注意在自旋的过程中会判断是否进入安全点同步,如果是则终止自旋。
int ObjectMonitor::TrySpin_VaryDuration (Thread * Self) {
//Knob_FixedSpin默认是0,表示固定自旋的次数
int ctr = Knob_FixedSpin ;
if (ctr != 0) {
//每一次while循环都是一次自旋,在指定的次数内抢占成功就是成功,否则失败
while (--ctr >= 0) {
//尝试抢占该锁,如果成功返回1
if (TryLock (Self) > 0) return 1 ;
//抢占失败,该方法直接返回0
SpinPause () ;
}
return 0 ;
}
//Knob_PreSpin的默认值是10
for (ctr = Knob_PreSpin + 1; --ctr >= 0 ; ) {
if (TryLock(Self) > 0) {
//抢占成功
int x = _SpinDuration ;
//Knob_SpinLimit的默认值是5000
if (x < Knob_SpinLimit) {
//增加_SpinDuration
//Knob_Poverty的默认值是1000,Knob_BonusB对的默认值是100
if (x < Knob_Poverty) x = Knob_Poverty ;
//即_SpinDuration的最小值是1100,最大值是5000
_SpinDuration = x + Knob_BonusB ;
}
return 1 ;
}
SpinPause () ;
}
ctr = _SpinDuration ;
//Knob_SpinBase的默认值是10
if (ctr < Knob_SpinBase) ctr = Knob_SpinBase ;
if (ctr <= 0) return 0 ;
//Knob_SuccRestrict默认为0
if (Knob_SuccRestrict && _succ != NULL) return 0 ;
//Knob_OState默认为3,NotRunnable用于判断目标线程是否退出,如果已退出则终止自旋
if (Knob_OState && NotRunnable (Self, (Thread *) _owner)) {
TEVENT (Spin abort - notrunnable [TOP]);
return 0 ;
}
//Knob_MaxSpinners默认为-1
int MaxSpin = Knob_MaxSpinners ;
if (MaxSpin >= 0) {
if (_Spinner > MaxSpin) {
TEVENT (Spin abort -- too many spinners) ;
return 0 ;
}
//原子的将_Spinner属性加1,不断循环直到修改成功
Adjust (&_Spinner, 1) ;
}
int hits = 0 ;
int msk = 0 ;
//Knob_CASPenalty默认值是-1
int caspty = Knob_CASPenalty ;
//Knob_OXPenalty默认值是-1
int oxpty = Knob_OXPenalty ;
//Knob_SpinSetSucc默认值是1
int sss = Knob_SpinSetSucc ;
if (sss && _succ == NULL ) _succ = Self ;
Thread * prv = NULL ;
// There are three ways to exit the following loop:
// 1. A successful spin where this thread has acquired the lock.
// 2. Spin failure with prejudice
// 3. Spin failure without prejudice
while (--ctr >= 0) {
if ((ctr & 0xFF) == 0) {
//0xFF就是256,即每自旋256次就需要检查是否开启了安全点同步
if (SafepointSynchronize::do_call_back()) {
//do_call_back返回true,说明进入了安全点同步
TEVENT (Spin: safepoint) ;
//跳转到Abort
goto Abort ;
}
//Knob_UsePause默认值是1
if (Knob_UsePause & 1) SpinPause () ;
//SpinCallbackFunction默认为NULL
int (*scb)(intptr_t,int) = SpinCallbackFunction ;
if (hits > 50 && scb != NULL) {
int abend = (*scb)(SpinCallbackArgument, 0) ;
}
}
if (Knob_UsePause & 2) SpinPause() ;
if (ctr & msk) continue ;
++hits ;
if ((hits & 0xF) == 0) {
//BackOffMask默认值是0
msk = ((msk << 2)|3) & BackOffMask ;
}
Thread * ox = (Thread *) _owner ;
if (ox == NULL) {
//该锁未被占用,通过cas抢占
ox = (Thread *) Atomic::cmpxchg_ptr (Self, &_owner, NULL) ;
if (ox == NULL) {
//抢占成功
if (sss && _succ == Self) {
_succ = NULL ;
}
//原子的将_Spinner减1
if (MaxSpin > 0) Adjust (&_Spinner, -1) ;
//增加_SpinDuration
int x = _SpinDuration ;
if (x < Knob_SpinLimit) {
if (x < Knob_Poverty) x = Knob_Poverty ;
_SpinDuration = x + Knob_Bonus ;
}
return 1 ;
}
//CAS抢占失败,caspty默认是-1
prv = ox ;
TEVENT (Spin: cas failed) ;
if (caspty == -2) break ;
if (caspty == -1) goto Abort ;
ctr -= caspty ;
continue ;
} //if结束
//如果占有该锁的线程发生改变了,oxpty默认值是-1
if (ox != prv && prv != NULL ) {
TEVENT (spin: Owner changed)
if (oxpty == -2) break ;
if (oxpty == -1) goto Abort ;
ctr -= oxpty ;
}
//记录下当前占用锁的线程
prv = ox ;
//如果占有该锁的线程退出了,则终止自旋
if (Knob_OState && NotRunnable (Self, ox)) {
TEVENT (Spin abort - notrunnable);
goto Abort ;
}
if (sss && _succ == NULL ) _succ = Self ;
} //while循环结束
TEVENT (Spin failure) ;
{
int x = _SpinDuration ;
if (x > 0) {
//Knob_Penalty的默认值是200
x -= Knob_Penalty ;
if (x < 0) x = 0 ;
//实际就是将_SpinDuration减去Knob_Penalty
_SpinDuration = x ;
}
}
Abort:
if (MaxSpin >= 0) Adjust (&_Spinner, -1) ;
if (sss && _succ == Self) {
_succ = NULL ;
OrderAccess::fence() ;
//尝试获取锁
if (TryLock(Self) > 0) return 1 ;
}
return 0 ;
}
int ObjectMonitor::TryLock (Thread * Self) {
for (;;) {
void * own = _owner ;
//如果不等于NULL说明某个线程依然占用该锁
if (own != NULL) return 0 ;
if (Atomic::cmpxchg_ptr (Self, &_owner, NULL) == NULL) {
//如果交换成功,说明抢占成功
assert (_recursions == 0, "invariant") ;
assert (_owner == Self, "invariant") ;
return 1 ;
}
//抢占失败返回-1
if (true) return -1 ;
}
}
extern "C" {
int SpinPause() {
return 0;
}
}
ObjectWaiter表示一个等待获取ObjectMonitor锁的线程,其定义如下:
其中next和prev属性表示 ObjectWaiter链表中的前后节点,_thread和_event都是关联的线程属性,TState用于描述当前ObjectWaiter的状态,刚创建时的状态是TS_RUN,加入到cxq链表中状态是TS_CXQ,加入到EntryList链表后变成TS_ENTER,加入到WaitSet链表中的状态就是TS_WAIT,另外两个状态枚举没有调用。_active用于记录当前线程是否开启了线程监控,如果开启了可以通过jmm接口获取线程运行的统计数据,比如锁抢占的次数和累计耗时。_notified属性用于记录该ObjectWaiter是否被某个线程唤醒了而不是因为线程中断唤醒的,_notifier_tid用于记录执行唤醒动作的线程指针。
三个方法的实现如下:
ObjectWaiter::ObjectWaiter(Thread* thread) {
_next = NULL;
_prev = NULL;
_notified = 0;
//初始状态
TState = TS_RUN ;
//关联的线程
_thread = thread;
_event = thread->_ParkEvent ;
_active = false;
assert (_event != NULL, "invariant") ;
}
void ObjectWaiter::wait_reenter_begin(ObjectMonitor *mon) {
JavaThread *jt = (JavaThread *)this->_thread;
_active = JavaThreadBlockedOnMonitorEnterState::wait_reenter_begin(jt, mon);
}
void ObjectWaiter::wait_reenter_end(ObjectMonitor *mon) {
JavaThread *jt = (JavaThread *)this->_thread;
JavaThreadBlockedOnMonitorEnterState::wait_reenter_end(jt, _active);
}
static bool wait_reenter_begin(JavaThread *java_thread, ObjectMonitor *obj_m) {
assert((java_thread != NULL), "Java thread should not be null here");
bool active = false;
if (is_alive(java_thread) && ServiceUtil::visible_oop((oop)obj_m->object())) {
active = contended_enter_begin(java_thread);
}
return active;
}
static void wait_reenter_end(JavaThread *java_thread, bool active) {
if (active) {
java_thread->get_thread_stat()->contended_enter_end();
}
//修改线程状态
set_thread_status(java_thread, java_lang_Thread::RUNNABLE);
}
//判断目标JavaThread是否存活的
static bool is_alive(JavaThread* java_thread) {
return java_thread != NULL && java_thread->threadObj() != NULL;
}
//如果这个oop是Java代码可见的,则返回true
static inline bool visible_oop(oop o) {
//如果是已经删除的JNI引用则不可见
if (o == JNIHandles::deleted_handle()) {
return false;
}
// instance
if (o->is_instance()) {
//如果是java_lang_Class的实例,即用来保存类静态属性的oop则返回false
//否则返回true
if (o->klass() != SystemDictionary::Class_klass()) {
return true;
}
//如果是基本类型
if (java_lang_Class::is_primitive(o)) {
return true;
}
//获取o所属的klass
Klass* k = java_lang_Class::as_Klass(o);
if (k->is_klass()) {
//普通Java类
if (k->oop_is_instance()) {
return true;
}
//对象数组
if (k->oop_is_objArray()) {
return true;
}
//多维数组
if (k->oop_is_typeArray()) {
return true;
}
}
return false;
}
// object arrays are visible if they aren't system object arrays
if (o->is_objArray()) {
return true;
}
// type arrays are visible
if (o->is_typeArray()) {
return true;
}
// everything else (Method*s, ...) aren't visible
return false;
}; // end of visible_oop()
static bool contended_enter_begin(JavaThread *java_thread) {
//修改Java状态
set_thread_status(java_thread, java_lang_Thread::BLOCKED_ON_MONITOR_ENTER);
//ThreadStatistics用于统计一些静态属性
ThreadStatistics* stat = java_thread->get_thread_stat();
stat->contended_enter();
//is_thread_monitoring_contention方法返回_thread_monitoring_contention_enabled属性,该属性默认为false,可通过jmm接口开启
bool active = ThreadService::is_thread_monitoring_contention();
if (active) {
stat->contended_enter_begin();
}
return active;
}
static void set_thread_status(JavaThread* java_thread,
java_lang_Thread::ThreadStatus state) {
java_lang_Thread::set_thread_status(java_thread->threadObj(), state);
}
其中wait_reenter_begin方法将线程的状态置为BLOCKED_ON_MONITOR_ENTER,如果通过JMM接口开启了JavaThread监控则记录当前线程开始锁抢占了;wait_reenter_end方法将线程的状态置为RUNNABLE,如果开启了JavaThread监控,则记录当前线程锁抢占结束了。
其中_thread_monitoring_contention_enabled属性的调用链如下:
jmm_SetBoolAttribute方法的实现如下:
该方法就是sun_management_ThreadImpl类的相关set方法的底层实现,如下:
即Java代码中可以通过此方法开启Java线程的运行情况的监控。
EnterI方法会初始化线程自旋相关配置,然后自旋尝试获取锁,获取失败后将当前线程加入到ObjectWaiter队列中,然后借助底层操作系统的互斥量让当前线程处于休眠状态,如果持有锁的线程释放了锁就会唤醒该线程,被唤醒后该线程会尝试获取锁,获取失败再自旋,依然获取失败再次进入休眠状态,如此循环直到获取锁为止,获取成功后将当前线程对应的ObjectWaiter从队列中移除。
void ATTR ObjectMonitor::EnterI (TRAPS) {
Thread * Self = THREAD ;
assert (Self->is_Java_thread(), "invariant") ;
//校验线程状态已经处于阻塞中
assert (((JavaThread *) Self)->thread_state() == _thread_blocked , "invariant") ;
if (TryLock (Self) > 0) {
//尝试获取锁,获取成功则返回
assert (_succ != Self , "invariant") ;
assert (_owner == Self , "invariant") ;
assert (_Responsible != Self , "invariant") ;
return ;
}
//初始化自旋相关配置参数
DeferredInitialize () ;
if (TrySpin (Self) > 0) {
//再次尝试自旋,获取锁成功则返回
assert (_owner == Self , "invariant") ;
assert (_succ != Self , "invariant") ;
assert (_Responsible != Self , "invariant") ;
return ;
}
//自旋获取锁失败,将当前线程加入到等待队列中并且park
assert (_succ != Self , "invariant") ;
assert (_owner != Self , "invariant") ;
assert (_Responsible != Self , "invariant") ;
//创建一个ObjectWaiter并初始化
ObjectWaiter node(Self) ;
Self->_ParkEvent->reset() ;
node._prev = (ObjectWaiter *) 0xBAD ;
node.TState = ObjectWaiter::TS_CXQ ;
ObjectWaiter * nxt ;
for (;;) {
node._next = nxt = _cxq ;
//原子的修改_cxq为node,如果修改成功则终止循环,表示已经成功加入到链表中
if (Atomic::cmpxchg_ptr (&node, &_cxq, nxt) == nxt) break ;
//修改失败,某个线程改变了cxq
if (TryLock (Self) > 0) {
//再次尝试获取锁,获取成功则返回
assert (_succ != Self , "invariant") ;
assert (_owner == Self , "invariant") ;
assert (_Responsible != Self , "invariant") ;
return ;
}
}
//SyncFlags对的默认值是0
if ((SyncFlags & 16) == 0 && nxt == NULL && _EntryList == NULL) {
//nxt或者_EntryList为NULL,说明当前线程是第一个阻塞的线程,将_Responsible原子的修改为当前线程
Atomic::cmpxchg_ptr (Self, &_Responsible, NULL) ;
}
TEVENT (Inflated enter - Contention) ;
int nWakeups = 0 ;
int RecheckInterval = 1 ;
for (;;) {
//尝试获取锁
if (TryLock (Self) > 0) break ;
assert (_owner != Self, "invariant") ;
if ((SyncFlags & 2) && _Responsible == NULL) {
//原子的将_Responsible置为Self
Atomic::cmpxchg_ptr (Self, &_Responsible, NULL) ;
}
//将目标线程park掉,底层通过操作系统的互斥量实现,让当前线程休眠
if (_Responsible == Self || (SyncFlags & 1)) {
TEVENT (Inflated enter - park TIMED) ;
Self->_ParkEvent->park ((jlong) RecheckInterval) ;
//增加等待时间,最大不超过1s
RecheckInterval *= 8 ;
if (RecheckInterval > 1000) RecheckInterval = 1000 ;
} else {
TEVENT (Inflated enter - park UNTIMED) ;
Self->_ParkEvent->park() ;
}
//线程被唤醒了,即某个占用锁的线程释放了锁,尝试抢占该锁
if (TryLock(Self) > 0) break ;
TEVENT (Inflated enter - Futile wakeup) ;
if (ObjectMonitor::_sync_FutileWakeups != NULL) {
//增加计数
ObjectMonitor::_sync_FutileWakeups->inc() ;
}
//增加计数
++ nWakeups ;
//Knob_SpinAfterFutile默认值是1,此时会再次尝试自旋获取锁
if ((Knob_SpinAfterFutile & 1) && TrySpin (Self) > 0) break ;
//Knob_ResetEvent默认值是0
if ((Knob_ResetEvent & 1) && Self->_ParkEvent->fired()) {
Self->_ParkEvent->reset() ;
OrderAccess::fence() ;
}
if (_succ == Self) _succ = NULL ;
//强制所有修改立即生效
OrderAccess::fence() ;
}
//for循环结束,当前线程已经获取了锁
assert (_owner == Self , "invariant") ;
assert (object() != NULL , "invariant") ;
//将其从EntryList或者cxq链表中移除
UnlinkAfterAcquire (Self, &node) ;
if (_succ == Self) _succ = NULL ;
assert (_succ != Self, "invariant") ;
if (_Responsible == Self) {
//将_Responsible置为NULL
_Responsible = NULL ;
OrderAccess::fence(); // Dekker pivot-point
}
if (SyncFlags & 8) {
OrderAccess::fence() ;
}
return ;
}
void ObjectMonitor::DeferredInitialize () {
//初始化完成时会将InitDone置为1,即只初始化第一次即可
if (InitDone > 0) return ;
if (Atomic::cmpxchg (-1, &InitDone, 0) != 0) {
//将其原子的修改为-1,如果修改失败说明有一个线程已经完成了修改
//自旋等待该线程完成初始化
while (InitDone != 1) ;
return ;
}
// SyncKnobs是一个配置项,用来配置跟自旋等待相关的属性
if (SyncKnobs == NULL) SyncKnobs = "" ;
//获取其字符长度
size_t sz = strlen (SyncKnobs) ;
//分配一个字符数组
char * knobs = (char *) malloc (sz + 2) ;
if (knobs == NULL) {
//分配失败抛出异常
vm_exit_out_of_memory (sz + 2, OOM_MALLOC_ERROR, "Parse SyncKnobs") ;
guarantee (0, "invariant") ;
}
//复制到knobs
strcpy (knobs, SyncKnobs) ;
//加1的字符置为0,表示字符串结束
knobs[sz+1] = 0 ;
for (char * p = knobs ; *p ; p++) {
if (*p == ':') *p = 0 ;
}
//初始化各项配置,kvGetInt负责查找配置项的值
#define SETKNOB(x) { Knob_##x = kvGetInt (knobs, #x, Knob_##x); }
SETKNOB(ReportSettings) ;
SETKNOB(Verbose) ;
SETKNOB(FixedSpin) ;
SETKNOB(SpinLimit) ;
SETKNOB(SpinBase) ;
SETKNOB(SpinBackOff);
SETKNOB(CASPenalty) ;
SETKNOB(OXPenalty) ;
SETKNOB(LogSpins) ;
SETKNOB(SpinSetSucc) ;
SETKNOB(SuccEnabled) ;
SETKNOB(SuccRestrict) ;
SETKNOB(Penalty) ;
SETKNOB(Bonus) ;
SETKNOB(BonusB) ;
SETKNOB(Poverty) ;
SETKNOB(SpinAfterFutile) ;
SETKNOB(UsePause) ;
SETKNOB(SpinEarly) ;
SETKNOB(OState) ;
SETKNOB(MaxSpinners) ;
SETKNOB(PreSpin) ;
SETKNOB(ExitPolicy) ;
SETKNOB(QMode);
SETKNOB(ResetEvent) ;
SETKNOB(MoveNotifyee) ;
SETKNOB(FastHSSEC) ;
#undef SETKNOB
if (Knob_Verbose) {
//检查配置的合法性
sanity_checks();
}
if (os::is_MP()) {
BackOffMask = (1 << Knob_SpinBackOff) - 1 ;
if (Knob_ReportSettings) ::printf ("BackOffMask=%X\n", BackOffMask) ;
} else {
Knob_SpinLimit = 0 ;
Knob_SpinBase = 0 ;
Knob_PreSpin = 0 ;
Knob_FixedSpin = -1 ;
}
if (Knob_LogSpins == 0) {
ObjectMonitor::_sync_FailedSpins = NULL ;
}
//释放knobs的内存
free (knobs) ;
//让修改立即生效
OrderAccess::fence() ;
//标识初始化完成
InitDone = 1 ;
}
void ObjectMonitor::UnlinkAfterAcquire (Thread * Self, ObjectWaiter * SelfNode)
{
assert (_owner == Self, "invariant") ;
assert (SelfNode->_thread == Self, "invariant") ;
if (SelfNode->TState == ObjectWaiter::TS_ENTER) {
//正常情况走此分支,将SelfNode从_EntryList中移除
//默认配置下,cxq链表中的节点会被转移到EntryList链表中,状态就置为TS_ENTER
ObjectWaiter * nxt = SelfNode->_next ;
ObjectWaiter * prv = SelfNode->_prev ;
if (nxt != NULL) nxt->_prev = prv ;
if (prv != NULL) prv->_next = nxt ;
if (SelfNode == _EntryList ) _EntryList = nxt ;
assert (nxt == NULL || nxt->TState == ObjectWaiter::TS_ENTER, "invariant") ;
assert (prv == NULL || prv->TState == ObjectWaiter::TS_ENTER, "invariant") ;
TEVENT (Unlink from EntryList) ;
} else {
guarantee (SelfNode->TState == ObjectWaiter::TS_CXQ, "invariant") ;
ObjectWaiter * v = _cxq ;
assert (v != NULL, "invariant") ;
//如果v不等于SelfNode直接进入下面的分支,如果等于执行后面的CAS逻辑,将_cxq修改为next,如果修改失败会进入if分支
if (v != SelfNode || Atomic::cmpxchg_ptr (SelfNode->_next, &_cxq, v) != v) {
if (v == SelfNode) {
assert (_cxq != v, "invariant") ;
//修改失败,说明有其他线程修改了cxq,这里重新获取cxq
v = _cxq ; // CAS above failed - start scan at head of list
}
ObjectWaiter * p ;
ObjectWaiter * q = NULL ;
//遍历找到SelfNode,将其移除
for (p = v ; p != NULL && p != SelfNode; p = p->_next) {
q = p ;
assert (p->TState == ObjectWaiter::TS_CXQ, "invariant") ;
}
assert (v != SelfNode, "invariant") ;
assert (p == SelfNode, "Node not found on cxq") ;
assert (p != _cxq, "invariant") ;
assert (q != NULL, "invariant") ;
assert (q->_next == p, "invariant") ;
q->_next = p->_next ;
}
TEVENT (Unlink from cxq) ;
}
//prev和next属性置为null
SelfNode->_prev = (ObjectWaiter *) 0xBAD ;
SelfNode->_next = (ObjectWaiter *) 0xBAD ;
SelfNode->TState = ObjectWaiter::TS_RUN ;
}
JavaThreadBlockedOnMonitorEnterState继承自JavaThreadStatusChanger,该类在构造函数中保存线程原来的状态,并在析构函数中恢复线程的原来的运行状态,其实现如下:
JavaThreadStatusChanger(JavaThread* java_thread,
java_lang_Thread::ThreadStatus state) : _old_state(java_lang_Thread::NEW) {
save_old_state(java_thread);
set_thread_status(state);
}
JavaThreadStatusChanger(JavaThread* java_thread) : _old_state(java_lang_Thread::NEW) {
save_old_state(java_thread);
}
~JavaThreadStatusChanger() {
set_thread_status(_old_state);
}
void save_old_state(JavaThread* java_thread) {
_java_thread = java_thread;
_is_alive = is_alive(java_thread);
if (is_alive()) {
//获取线程状态
_old_state = java_lang_Thread::get_thread_status(_java_thread->threadObj());
}
}
void set_thread_status(java_lang_Thread::ThreadStatus state) {
if (is_alive()) {
//如果线程是存活的则设置线程状态
set_thread_status(_java_thread, state);
}
}
static void set_thread_status(JavaThread* java_thread,
java_lang_Thread::ThreadStatus state) {
java_lang_Thread::set_thread_status(java_thread->threadObj(), state);
}
bool is_alive() {
return _is_alive;
}
JavaThreadBlockedOnMonitorEnterState同样是借助构造和析构函数完成状态变更的,其实现如下:
JavaThreadBlockedOnMonitorEnterState(JavaThread *java_thread, ObjectMonitor *obj_m) :
_stat(NULL), _active(false), JavaThreadStatusChanger(java_thread) {
assert((java_thread != NULL), "Java thread should not be null here");
_active = false;
if (is_alive() && ServiceUtil::visible_oop((oop)obj_m->object()) && obj_m->contentions() > 0) {
_stat = java_thread->get_thread_stat();
//contended_enter_begin方法会修改线程状态为BLOCKED_ON_MONITOR_ENTER
_active = contended_enter_begin(java_thread);
}
}
~JavaThreadBlockedOnMonitorEnterState() {
//会调用父类的析构函数将线程状态还原回去
if (_active) {
_stat->contended_enter_end();
}
}
//返回抢占这个锁的线程数
inline intptr_t ObjectMonitor::contentions() const {
return _count;
}
其中涉及的线程状态的定义如下:
OSThreadContendState的实现类似,用于修改原生的本地线程的状态,其实现如下:
其中原生线程的状态的定义如下:
ThreadBlockInVM用于修改java线程的状态,此状态是JVM内部使用的,用于实现让当前线程进入安全点,其实现如下:
trans_and_fence在切换线程状态时会判断安全点同步是否开启,如果开启了则阻塞当前线程,即让当前线程停在安全点上,具体实现细节可参考《Hotspot 垃圾回收之SafepointSynchronize(一) 源码解析》。
enter方法用于获取某个ObjectMonitor对应的重量级锁,为了尽可能减少对系统互斥量的使用,减少锁抢占的性能损耗,ObjectMonitor多次调用TrySpin方法让当前线程自旋抢占锁,进入EnterI方法前会调用一次,进入EnterI后会调用一次,然后park和TrySpin在一个for循环中先后执行,直到成功获取锁为止。
//可能多个线程同时进入此方法
void ATTR ObjectMonitor::enter(TRAPS) {
//获取当前线程指针
Thread * const Self = THREAD ;
void * cur ;
//原子的设置owner属性,如果_owner属性是NULL就将其设置为Self,否则返回当前的_owner属性
cur = Atomic::cmpxchg_ptr (Self, &_owner, NULL) ;
if (cur == NULL) {
//设置成功,说明该Monitor没有被人占用
assert (_recursions == 0 , "invariant") ;
assert (_owner == Self, "invariant") ;
// CONSIDER: set or assert OwnerIsThread == 1
return ;
}
if (cur == Self) {
//设置失败,说明该Monitor就是当前线程占用的,此处进入enter是嵌套加锁情形
_recursions ++ ;
return ;
}
//轻量级锁膨胀成重量级锁时,将owner设置为lock属性
if (Self->is_lock_owned ((address)cur)) {
assert (_recursions == 0, "internal state error");
//正常轻量级膨胀成重量级锁时,之前已经获取轻量级锁的线程不需要二次调用enter方法
//此时再调用enter方法说明是锁嵌套情形,将_recursions置为1
_recursions = 1 ;
//将owner置为当前线程
_owner = Self ;
//表明当前线程是获取轻量级锁的
OwnerIsThread = 1 ;
return ;
}
//该Monitor被其他某个线程占用了,需要抢占
assert (Self->_Stalled == 0, "invariant") ;
//记录需要抢占的Monitor指针
Self->_Stalled = intptr_t(this) ;
//Knob_SpinEarly默认为1,即为true
//TrySpin让当前线程自旋,自旋的次数默认可以自适应调整,如果进入安全点同步则退出自旋,返回1表示抢占成功
if (Knob_SpinEarly && TrySpin (Self) > 0) {
assert (_owner == Self , "invariant") ;
assert (_recursions == 0 , "invariant") ;
assert (((oop)(object()))->mark() == markOopDesc::encode(this), "invariant") ;
//将_Stalled置为NULL
Self->_Stalled = 0 ;
return ;
}
//自旋若干次数后依然抢占失败
assert (_owner != Self , "invariant") ;
assert (_succ != Self , "invariant") ;
assert (Self->is_Java_thread() , "invariant") ;
JavaThread * jt = (JavaThread *) Self ;
//校验安全点同步未完成
assert (!SafepointSynchronize::is_at_safepoint(), "invariant") ;
assert (jt->thread_state() != _thread_blocked , "invariant") ;
assert (this->object() != NULL , "invariant") ;
assert (_count >= 0, "invariant") ;
//原子的将_count属性加1,表示增加了一个抢占该锁的线程
Atomic::inc_ptr(&_count);
EventJavaMonitorEnter event;
{ //修改Java线程状态为BLOCKED_ON_MONITOR_ENTER,此代码块退出后还原成原来的
JavaThreadBlockedOnMonitorEnterState jtbmes(jt, this);
Self->set_current_pending_monitor(this);
DTRACE_MONITOR_PROBE(contended__enter, this, object(), jt);
if (JvmtiExport::should_post_monitor_contended_enter()) {
JvmtiExport::post_monitor_contended_enter(jt, this);
}
//修改OS线程状态为MONITOR_WAIT,此代码块退出后还原成原来的
OSThreadContendState osts(Self->osthread());
//让当前线程的调用栈帧可以walkable,即可以被遍历,需要记录上一次执行的Java字节码
//然后切换线程的运行状态,从_thread_in_vm切换成_thread_blocked,切换的过程如果进入安全点同步则会被阻塞,此代码块退出将状态从_thread_blocked切换成_thread_in_vm,同样切换过程中如果进入安全点同步则被阻塞
ThreadBlockInVM tbivm(jt);
// TODO-FIXME: change the following for(;;) loop to straight-line code.
for (;;) {
//将线程的_suspend_equivalent属性置为true,该属性表明当前线程处于悬浮状态
jt->set_suspend_equivalent();
//会通过自旋,park等方式不断循环尝试获取锁,直到成功获取锁为止
EnterI (THREAD) ;
//ExitSuspendEquivalent默认返回false
if (!ExitSuspendEquivalent(jt)) break ;
// 等待suspended当前线程的线程
_recursions = 0 ;
_succ = NULL ;
exit (false, Self) ;
jt->java_suspend_self();
}
//将关联的ObjectMonitor置为null,表示当前线程已经不在阻塞状态了
Self->set_current_pending_monitor(NULL);
}
//原子的将count属性减1,表示已经有一个线程成功获取锁
Atomic::dec_ptr(&_count);
assert (_count >= 0, "invariant") ;
Self->_Stalled = 0 ;
// Must either set _recursions = 0 or ASSERT _recursions == 0.
assert (_recursions == 0 , "invariant") ;
assert (_owner == Self , "invariant") ;
assert (_succ != Self , "invariant") ;
assert (((oop)(object()))->mark() == markOopDesc::encode(this), "invariant") ;
DTRACE_MONITOR_PROBE(contended__entered, this, object(), jt);
if (JvmtiExport::should_post_monitor_contended_entered()) {
JvmtiExport::post_monitor_contended_entered(jt, this);
}
if (event.should_commit()) {
event.set_klass(((oop)this->object())->klass());
event.set_previousOwner((TYPE_JAVALANGTHREAD)_previous_owner_tid);
event.set_address((TYPE_ADDRESS)(uintptr_t)(this->object_addr()));
event.commit();
}
if (ObjectMonitor::_sync_ContendedLockAttempts != NULL) {
//增加计数
ObjectMonitor::_sync_ContendedLockAttempts->inc() ;
}
}
bool ObjectMonitor::ExitSuspendEquivalent (JavaThread * jSelf) {
int Mode = Knob_FastHSSEC ;
//Knob_FastHSSEC默认为0,即为false
if (Mode && !jSelf->is_external_suspend()) {
assert (jSelf->is_suspend_equivalent(), "invariant") ;
jSelf->clear_suspend_equivalent() ;
if (2 == Mode) OrderAccess::storeload() ;
if (!jSelf->is_external_suspend()) return false ;
// We raced a suspension -- fall thru into the slow path
TEVENT (ExitSuspendEquivalent - raced) ;
jSelf->set_suspend_equivalent() ;
}
//该方法默认返回false
return jSelf->handle_special_suspend_equivalent_condition() ;
}
bool handle_special_suspend_equivalent_condition() {
assert(is_suspend_equivalent(),
"should only be called in a suspend equivalence condition");
MutexLockerEx ml(SR_lock(), Mutex::_no_safepoint_check_flag);
bool ret = is_external_suspend();
if (!ret) {
clear_suspend_equivalent();
}
return ret;
}
bool is_external_suspend() const {
return (_suspend_flags & _external_suspend) != 0;
}
其中_suspend_flags的调用链如下:
上述调用中设置external_suspend的JVM_SuspendThread方法就是Thread类suspend0本地方法的实现,是Thread的suspend方法的底层实现,该方法是一个已经被废弃的方法,因为该方法容易导致死锁,如下: