掌握Android和Java线程原理下,Android面试基础技能罗列

uint age = mark->age();

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

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

JavaThread* biased_thread = mark->biased_locker();

if (biased_thread == NULL) {

// 匿名偏向

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;

}

// 判断线程是否存活

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;

}

}

}

//如果线程不存活,则将markword设置为匿名偏向锁或者无锁状态

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;

}

// 线程还存活则遍历线程栈中所有的Lock Record

GrowableArray<MonitorInfo*>* 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);

// 如果能找到对应的Lock Record说明偏向的线程还在执行同步代码块中的代码

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);

}

// 需要升级为轻量级锁,直接修改偏向线程栈中的Lock Record

markOop mark = markOopDesc::encode((BasicLock*) NULL);

highest_lock = mon_info->lock();

highest_lock->set_displaced_header(mark);

}

}

if (highest_lock != NULL) {

// 修改第一个Lock Record为无锁状态,然后将obj的mark word设置为指向该Lock Record的指针

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 {

// 将mark word设置为无锁状态

obj->set_mark(unbiased_prototype);

}

}

return BiasedLocking::BIAS_REVOKED;

}

了解了偏向锁的加锁流程,再接着看自旋锁和重量级锁的加锁流程slow_enter。

轻量级锁加锁流程

void ObjectSynchronizer::slow_enter(Handle obj, BasicLock* lock, TRAPS) {

markOop mark = obj->mark();

assert(!mark->has_bias_pattern(), “should not see bias pattern here”);

//是否为无锁状态

if (mark->is_neutral()) {

//如果是无锁状态,通过cas加轻量级锁,cas成功则表示加锁成功

lock->set_displaced_header(mark);

if (mark == (markOop) Atomic::cmpxchg_ptr(lock, obj()->mark_addr(), mark)) {

TEVENT (slow_enter: release stacklock) ;

return ;

}

} else

//如果是有锁状态,判断是否是同一把锁,如果是,则直接进入临界区

if (mark->has_locker() && THREAD->is_lock_owned((address)mark->locker())) {

assert(lock != mark->locker(), “must not re-lock the same lock”);

assert(lock != (BasicLock*)obj->mark(), “don’t relock with same BasicLock”);

lock->set_displaced_header(NULL);

return;

}

lock->set_displaced_header(markOopDesc::unused_mark());

//如果上面两种状态都不满足,说明出现了锁的竞争情况,轻量级锁需要膨胀成重量级锁

ObjectSynchronizer::inflate(THREAD, obj())->enter(THREAD);

}

slow_enter会判断是否是无锁,如果是,则通过CAS进行轻量级锁加锁则,如果有锁,则判断是否是同意把锁,如果是,也可以直接进入临界区,如果不是,轻量级锁需要调用flate函数膨胀成重量级锁,膨胀成重量级锁后,执行enter方法。我们先看看膨胀过程。

轻量级锁膨胀过程

我们接着看inflate是如何进行膨胀的

ObjectMonitor * ATTR ObjectSynchronizer::inflate (Thread * Self, oop object) {

for (;😉 {

const markOop mark = object->mark() ;

assert (!mark->has_bias_pattern(), “invariant”) ;

// 判断是否有monitor,这个monitor就是管程对象,如果已经有了管程,说明已经是重量级锁了,如果是重量级锁则退出膨胀

if (mark->has_monitor()) {

ObjectMonitor * inf = mark->monitor() ;

assert (inf->header()->is_neutral(), “invariant”);

assert (inf->object() == object, “invariant”) ;

assert (ObjectSynchronizer::verify_objmon_isinpool(inf), “monitor is invalid”);

return inf ;

}

//其他线程正在进入膨胀过程,即自旋锁升级重量级锁的过程,当前线程需要进行等待

if (mark == markOopDesc::INFLATING()) {

TEVENT (Inflate: spin while INFLATING) ;

ReadStableMark(object) ;

continue ;

}

//判断是否是轻量级锁

if (mark->has_locker()) {

//获取一个可用管程,ObjectMonitor就是JVM的管程对象

ObjectMonitor * m = omAlloc (Self) ;

m->Recycle();

m->_Responsible = NULL ;

m->OwnerIsThread = 0 ;

m->_recursions = 0 ;

m->_SpinDuration = ObjectMonitor::Knob_SpinLimit ; // Consider: maintain by type/class

markOop cmp = (markOop) Atomic::cmpxchg_ptr (markOopDesc::INFLATING(), object->mark_addr(), mark) ;

//CAS操作标识Mark Word正在膨胀

if (cmp != mark) {

omRelease (Self, m, true) ;

continue ;

}

//CAS成功,初始化管程ObjectMonitor的信息

markOop dmw = mark->displaced_mark_helper() ;

assert (dmw->is_neutral(), “invariant”) ;

m->set_header(dmw) ;

m->set_owner(mark->locker());

guarantee (object->mark() == markOopDesc::INFLATING(), “invariant”) ;

object->release_set_mark(markOopDesc::encode(m));

if (ObjectMonitor::_sync_Inflations != NULL) ObjectMonitor::_sync_Inflations->inc() ;

return m ;

}

……

}

}

在flate膨胀过程中,我们获取了重量级锁ObjectMonitor,这个就是JVM的管程对象,并且调用管程的enter方法,开始进入管程模型。

重量级锁加锁流程

接着看看ObjectMonitor管程的enter方法里面做了什么事情。

void ATTR ObjectMonitor::enter(TRAPS) {

// The following code is ordered to check the most common cases first

// and to reduce RTS->RTO cache line upgrades on SPARC and IA32 processors.

Thread * const Self = THREAD ;

void * cur ;

……

//尝试自旋获取锁

if (Knob_SpinEarly && TrySpin (Self) > 0) {

assert (_owner == Self , “invariant”) ;

assert (_recursions == 0 , “invariant”) ;

assert (((oop)(object()))->mark() == markOopDesc::encode(this), “invariant”) ;

Self->_Stalled = 0 ;

return ;

}

……

for (;😉 {

……

//自旋失败则进入EnterI流程。

EnterI (THREAD) ;

……

}

……

}

ObjectMonitor的enter方法中,会先通过自旋获取锁,如果自旋超过一定的次数,则自旋失败,进入EnterI流程。

void ATTR ObjectMonitor::EnterI (TRAPS) {

Thread * Self = THREAD ;

//尝试获取锁

if (TryLock (Self) > 0) {

return ;

}

//再次尝试自旋

if (TrySpin (Self) > 0) {

return ;

}

//将当前线程封装成ObjectWaiter对象

ObjectWaiter node(Self) ;

Self->_ParkEvent->reset() ;

node._prev = (ObjectWaiter *) 0xBAD ;

node.TState = ObjectWaiter::TS_CXQ ;

ObjectWaiter * nxt ;

for (;😉 {

//通过循环确保ObjectWaiter插入了队列

nod

e._next = nxt = _cxq ;

if (Atomic::cmpxchg_ptr (&node, &_cxq, nxt) == nxt) break ;

// 继续挣扎一下,尝试获取锁

if (TryLock (Self) > 0) {

return ;

}

}

if ((SyncFlags & 16) == 0 && nxt == NULL && _EntryList == NULL) {

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) {

Atomic::cmpxchg_ptr (Self, &_Responsible, NULL) ;

}

// park self

if (_Responsible == Self || (SyncFlags & 1)) {

//延时挂起当前线程

Self->_ParkEvent->park ((jlong) RecheckInterval) ;

RecheckInterval *= 8 ;

if (RecheckInterval > 1000) RecheckInterval = 1000 ;

} else {

TEVENT (Inflated enter - park UNTIMED) ;

//挂起当前线程

Self->_ParkEvent->park() ;

}

//依然在尝试获取锁

if (TryLock(Self) > 0) break ;

……

}

……

return ;

}

EnterI主要做了这两事情

  1. 将当前线程封装成ObjectWaiter,并放入等待队列

  2. 调用ParkEvent的park方法,ParkEvent是Thread对象的内部类,park方法会将当前线程进行挂起。

可以看到,EnterI的方法中不断的在调用tryLock尝试获取锁,主要原因也是因为将线程挂起,然后再唤醒的性能开销是比较大的,能不挂起线程就最好不挂起线程。

加锁的流程讲完了,接着来看一下释放锁的流程。

释放锁流程

释放锁的入口逻辑如下:

CASE(_monitorexit): {

//1,获取对象头

oop lockee = STACK_OBJECT(-1);

CHECK_NULL(lockee);

BasicObjectLock* limit = istate->monitor_base();

BasicObjectLock* most_recent = (BasicObjectLock*) istate->stack_base();

while (most_recent != limit ) {

if ((most_recent)->obj() == lockee) {

BasicLock* lock = most_recent->lock();

//2,获取对象头中的markword头

markOop header = lock->displaced_header();

most_recent->set_obj(NULL);

if (header != NULL) {

if (Atomic::cmpxchg_ptr(header, lockee->mark_addr(), lock) != lock) {

// restore object for the slow case

most_recent->set_obj(lockee);

//3,执行释放锁的逻辑

CALL_VM(InterpreterRuntime::monitorexit(THREAD, most_recent), handle_exception);

}

}

UPDATE_PC_AND_TOS_AND_CONTINUE(1, -1);

}

most_recent++;

}

// Need to throw illegal monitor state exception

CALL_VM(InterpreterRuntime::throw_illegal_monitor_state_exception(THREAD), handle_exception);

ShouldNotReachHere();

}

_monitorexit的入口逻辑主要调用InterpreterRuntime::monitorexit函数执行释放锁的逻辑,接着往下看

IRT_ENTRY_NO_ASYNC(void, InterpreterRuntime::monitorexit(JavaThread* thread, BasicObjectLock* elem))

#ifdef ASSERT

thread->last_frame().interpreter_frame_verify_monitor(elem);

#endif

Handle h_obj(thread, elem->obj());

assert(Universe::heap()->is_in_reserved_or_null(h_obj()),

“must be NULL or an object”);

if (elem == NULL || h_obj()->is_unlocked()) {

THROW(vmSymbols::java_lang_IllegalMonitorStateException());

}

ObjectSynchronizer::slow_exit(h_obj(), elem->lock(), thread);

// Free entry. This must be done here, since a pending exception might be installed on

// exit. If it is not cleared, the exception handling code will try to unlock the monitor again.

elem->set_obj(NULL);

#ifdef ASSERT

thread->last_frame().interpreter_frame_verify_monitor(elem);

#endif

IRT_END

这里调用了slow_exit函数

void ObjectSynchronizer::slow_exit(oop object, BasicLock* lock, TRAPS) {

fast_exit (object, lock, THREAD) ;

}

void ObjectSynchronizer::fast_exit(oop object, BasicLock* lock, TRAPS) {

assert(!object->mark()->has_bias_pattern(), “should not see bias pattern here”);

// if displaced header is null, the previous enter is recursive enter, no-op

markOop dhw = lock->displaced_header();

markOop mark ;

if (dhw == NULL) {

//重入锁,直接释放

mark = object->mark() ;

assert (!mark->is_neutral(), “invariant”) ;

if (mark->has_locker() && mark != markOopDesc::INFLATING()) {

assert(THREAD->is_lock_owned((address)mark->locker()), “invariant”) ;

}

if (mark->has_monitor()) {

ObjectMonitor * m = mark->monitor() ;

assert(((oop)(m->object()))->mark() == mark, “invariant”) ;

assert(m->is_entered(THREAD), “invariant”) ;

}

return ;

}

mark = object->mark() ;

if (mark == (markOop) lock) {

//轻量级锁,直接释放

assert (dhw->is_neutral(), “invariant”) ;

if ((markOop) Atomic::cmpxchg_ptr (dhw, object->mark_addr(), mark) == mark) {

TEVENT (fast_exit: release stacklock) ;

return;

}

}

//重量级锁释放

ObjectSynchronizer::inflate(THREAD, object)->exit (true, THREAD) ;

}

slow_exit函数里面又调用了fast_exit,这一块的调用逻辑我觉得JVM的团队需要优化一下,方法名给人很大的歧义性。fast_exit主要做了三件事

  1. 如果是重入锁,则直接return

  2. 如果是轻量级锁,则CAS重写mardword信息,释放锁

  3. 如果是重量级锁,通过infalte获得Monitor,然后调用Monitor的exit方法。

重量级锁释放流程

void ATTR ObjectMonitor::exit(bool not_suspended, TRAPS) {

Thread * Self = THREAD ;

……

for (;😉 {

assert (THREAD == _owner, “invariant”) ;

……

ObjectWaiter * w = NULL ;

int QMode = Knob_QMode ;

if (QMode == 2 && _cxq != NULL) {

w = _cxq ;

assert (w != NULL, “invariant”) ;

assert (w->TState == ObjectWaiter::TS_CXQ, “Invariant”) ;

ExitEpilog (Self, w) ;

return ;

}

if (QMode == 3 && _cxq != NULL) {

w = _cxq ;

for (;😉 {

assert (w != NULL, “Invariant”) ;

ObjectWaiter * u = (ObjectWaiter *) Atomic::cmpxchg_ptr (NULL, &_cxq, w) ;

if (u == w) break ;

w = u ;

}

assert (w != NULL , “invariant”) ;

ObjectWaiter * q = NULL ;

ObjectWaiter * p ;

for (p = w ; p != NULL ; p = p->_next) {

guarantee (p->TState == ObjectWaiter::TS_CXQ, “Invariant”) ;

p->TState = ObjectWaiter::TS_ENTER ;

p->_prev = q ;

q = p ;

}

// Append the RATs to the EntryList

// TODO: organize EntryList as a CDLL so we can locate the tail in constant-time.

ObjectWaiter * Tail ;

for (Tail = _EntryList ; Tail != NULL && Tail->_next != NULL ; Tail = Tail->_next) ;

if (Tail == NULL) {

_EntryList = w ;

} else {

Tail->_next = w ;

w->_prev = Tail ;

}

// Fall thru into code that tries to wake a successor from EntryList

}

if (QMode == 4 && _cxq != NULL) {

w = _cxq ;

for (;😉 {

assert (w != NULL, “Invariant”) ;

ObjectWaiter * u = (ObjectWaiter *) Atomic::cmpxchg_ptr (NULL, &_cxq, w) ;

if (u == w) break ;

w = u ;

}

assert (w != NULL , “invariant”) ;

ObjectWaiter * q = NULL ;

ObjectWaiter * p ;

for (p = w ; p != NULL ; p = p->_next) {

guarantee (p->TState == ObjectWaiter::TS_CXQ, “Invariant”) ;

p->TState = ObjectWaiter::TS_ENTER ;

p->_prev = q ;

q = p ;

}

// Prepend the RATs to the EntryList

if (_EntryList != NULL) {

q->_next = _EntryList ;

_EntryList->_prev = q ;

}

_EntryList = w ;

// Fall thru into code that tries to wake a successor from EntryList

}

w = _EntryList ;

if (w != NULL) {

assert (w->TState == ObjectWaiter::TS_ENTER, “invariant”) ;

ExitEpilog (Self, w) ;

return ;

}

if (QMode == 1) {

// QMode == 1 : drain cxq to EntryList, reversing order

// We also reverse the order of the list.

ObjectWaiter * s = NULL ;

ObjectWaiter * t = w ;

ObjectWaiter * u = NULL ;

while (t != NULL) {

guarantee (t->TState == ObjectWaiter::TS_CXQ, “invariant”) ;

t->TState = ObjectWaiter::TS_ENTER ;

u = t->_next ;

t->_prev = u ;

t->_next = s ;

s = t;

t = u ;

}

_EntryList = s ;

assert (s != NULL, “invariant”) ;

} else {

// QMode == 0 or QMode == 2

_EntryList = w ;

ObjectWaiter * q = NULL ;

ObjectWaiter * p ;

for (p = w ; p != NULL ; p = p->_next) {

guarantee (p->TState == ObjectWaiter::TS_CXQ, “Invariant”) ;

p->TState = ObjectWaiter::TS_ENTER ;

p->_prev = q ;

q = p ;

}

}

if (_succ != NULL) continue;

w = _EntryList ;

if (w != NULL) {

guarantee (w->TState == ObjectWaiter::TS_ENTER, “invariant”) ;

ExitEpilog (Self, w) ;

return ;

}

}

}

exit函数主要的逻辑是根据QMode,也就是优先级的模式,从调用EntryList中取出一个线程,并调用ExitEpilog函数进行唤醒工作。

void ObjectMonitor::ExitEpilog (Thread * Self, ObjectWaiter * Wakee) {

assert (_owner == Self, “invariant”) ;

_succ = Knob_SuccEnabled ? Wakee->_thread : NULL ;

ParkEvent * Trigger = Wakee->_event ;

Wakee = NULL ;

// Drop the lock

OrderAccess::release_store_ptr (&_owner, NULL) ;

OrderAccess::fence() ; // ST _owner vs LD in unpark()

if (SafepointSynchronize::do_call_back()) {

TEVENT (unpark before SAFEPOINT) ;

}

//将线程唤醒

Trigger->unpark() ;

}

到这里,HotSpot版本JVM中的Synchronize实现原理已经讲完了。接下来我们再看一下Art虚拟机Synchronize的实现原理,由于他们有很多类似的地方,所以Art中的Synchronize实现逻辑不会不会非常详细的去讲,我们看一下大概流程即可。

Art中的实现原理


Art中Synchronize入口和出口都在interpreter_switch_impl解释器的ExecuteSwitchImpl函数中。

/art/runtime/interpreter/interpreter_switch_impl.cc

进入管程

JValue ExecuteSwitchImpl(Thread* self, const DexFile::CodeItem* code_item,

ShadowFrame& shadow_frame, JValue result_register,

bool interpret_one_instruction) {

constexpr bool do_assignability_check = do_access_check;

self->VerifyStack();

uint32_t dex_pc = shadow_frame.GetDexPC();

const auto* const instrumentation = Runtime::Current()->GetInstrumentation();

const uint16_t* const insns = code_item->insns_;

const Instruction* inst = Instruction::At(insns + dex_pc);

uint16_t inst_data;

ArtMethod* method = shadow_frame.GetMethod();

jit::Jit* jit = Runtime::Current()->GetJit();

do {

dex_pc = inst->GetDexPc(insns);

shadow_frame.SetDexPC(dex_pc);

TraceExecution(shadow_frame, inst, dex_pc);

inst_data = inst->Fetch16(0);

switch (inst->Opcode(inst_data)) {

……

//Synchronize入口

case Instruction::MONITOR_ENTER: {

PREAMBLE();

ObjPtrmirror::Object obj = shadow_frame.GetVRegReference(inst->VRegA_11x(inst_data));

if (UNLIKELY(obj == nullptr)) {

ThrowNullPointerExceptionFromInterpreter();

HANDLE_PENDING_EXCEPTION();

} else {

DoMonitorEnter<do_assignability_check>(self, &shadow_frame, obj);

POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_1xx);

}

break;

}

//Synchronize出口

case Instruction::MONITOR_EXIT: {

PREAMBLE();

ObjPtrmirror::Object obj = shadow_frame.GetVRegReference(inst->VRegA_11x(inst_data));

if (UNLIKELY(obj == nullptr)) {

ThrowNullPointerExceptionFromInterpreter();

HANDLE_PENDING_EXCEPTION();

} else {

DoMonitorExit<do_assignability_check>(self, &shadow_frame, obj);

POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_1xx);

}

break;

}

……

}

} while (!interpret_one_instruction);

// Record where we stopped.

shadow_frame.SetDexPC(inst->GetDexPc(insns));

return result_register;

} // NOLINT(readability/fn_siz

先看Art是如何加锁的,它的处理逻辑再DoMonitorEnter函数中

加锁流程

/art/runtime/interpreter/interpreter_common.h

static inline void DoMonitorEnter(Thread* self, ShadowFrame* frame, ObjPtrmirror::Object ref)

NO_THREAD_SAFETY_ANALYSIS

REQUIRES(!Roles::uninterruptible_) {

StackHandleScope<1> hs(self);

Handlemirror::Object h_ref(hs.NewHandle(ref));

h_ref->MonitorEnter(self);

if (kMonitorCounting && frame->GetMethod()->MustCountLocks()) {

frame->GetLockCountData().AddMonitor(self, h_ref.Get());

}

}

里面最终调用了MonitorEnter函数。

/art/runtime/monitor.cc

mirror::Object* Monitor::MonitorEnter(Thread* self, mirror::Object* obj, bool trylock) {

DCHECK(self != nullptr);

DCHECK(obj != nullptr);

self->AssertThreadSuspensionIsAllowable();

obj = FakeLock(obj);

uint32_t thread_id = self->GetThreadId();

size_t contention_count = 0;

StackHandleScope<1> hs(self);

Handlemirror::Object h_obj(hs.NewHandle(obj));

while (true) {

//获取LockWord,类似JVM中的MarkWord

LockWord lock_word = h_obj->GetLockWord(false);

switch (lock_word.GetState()) {

case LockWord::kUnlocked: {

//无锁状态,则进行轻量级锁的加锁过程

LockWord thin_locked(LockWord::FromThinLockId(thread_id, 0, lock_word.GCState()));

if (h_obj->CasLockWordWeakAcquire(lock_word, thin_locked)) {

AtraceMonitorLock(self, h_obj.Get(), false /* is_wait */);

return h_obj.Get(); // Success!

}

continue; // Go again.

}

case LockWord::kThinLocked: {

//轻量级锁

uint32_t owner_thread_id = lock_word.ThinLockOwner();

// 判断lock_word的threadid是否相等

if (owner_thread_id == thread_id){

uint32_t new_count = lock_word.ThinLockCount() + 1;

if (LIKELY(new_count <= LockWord::kThinLockMaxCount)) {

//如果相等,并且小于轻量级锁的最大数量,则直接进入临界区

LockWord thin_locked(LockWord::FromThinLockId(thread_id,

new_count,

lock_word.GCState()));

if (!kUseReadBarrier) {

h_obj->SetLockWord(thin_locked, false /* volatile */);

AtraceMonitorLock(self, h_obj.Get(), false /* is_wait */);

return h_obj.Get(); // Success!

} else {

// Use CAS to preserve the read barrier state.

if (h_obj->CasLockWordWeakRelaxed(lock_word, thin_locked)) {

AtraceMonitorLock(self, h_obj.Get(), false /* is_wait */);

return h_obj.Get(); // Success!

}

}

continue; // Go again.

} else {

// 如果超出轻量级锁的数量,则进行重量级锁的加锁流程

InflateThinLocked(self, h_obj, lock_word, 0);

}

} else {

//lock_word的threadid和当前线程的threadid不等,升级成重量级锁并加锁

if (trylock) {

return nullptr;

}

// Contention.

contention_count++;

Runtime* runtime = Runtime::Current();

if (contention_count <= runtime->GetMaxSpinsBeforeThinLockInflation()) {

sched_yield();

} else {

contention_count = 0;

// No ordering required for initial lockword read. Install rereads it anyway.

InflateThinLocked(self, h_obj, lock_word, 0);

}

}

continue; // Start from the beginning.

}

case LockWord::kFatLocked: {

//重量级锁

QuasiAtomic::ThreadFenceAcquire();

//获取monitor

Monitor* mon = lock_word.FatLockMonitor()

//尝试获取锁

if (trylock) {

return mon->TryLock(self) ? h_obj.Get() : nullptr;

} else {

mon->Lock(self);

return h_obj.Get(); // Success!

}

}

default: {

LOG(FATAL) << "Invalid monitor state " << lock_word.GetState();

UNREACHABLE();

}

}

}

}

MonitorEnter函数中做的事情主要如下:

  1. 如果是无锁,通过CAS加轻量级锁,调用continue,进入步骤2。

  2. 如果是轻量级锁,判断LockWord的threadId和当前线程的ThreadId是否相等,如果相等,并且轻量级锁没有超过最大限制的情况下,return退出循环,进入临界区。如果不相等,则通过InflateThinLocked升级成重量级锁,升级的过程主要是创建和初始化Monitor的过程,调用continue,进入不走3。

  3. 如果是重量级锁,通过调用Monitor的lock函数获取锁

接着看lock获取锁的过程

/art/runtime/monitor.cc

void Monitor::Lock(Thread* self) {

MutexLock mu(self, monitor_lock_);

while (true) {

//尝试获取锁

if (TryLockLocked(self)) {

return;

}

// Contended.

const bool log_contention = (lock_profiling_threshold_ != 0);

uint64_t wait_start_ms = log_contention ? MilliTime() : 0;

ArtMethod* owners_method = locking_method_;

uint32_t owners_dex_pc = locking_dex_pc_;

// Do this before releasing the lock so that we don’t get deflated.

size_t num_waiters = num_waiters_;

++num_waiters_;

monitor_lock_.Unlock(self); // Let go of locks in order.

self->SetMonitorEnterObject(GetObject());

{

ScopedThreadSuspension tsc(self, kBlocked); // Change to blocked and give up mutator_lock_.

uint32_t original_owner_thread_id = 0u;

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
img

学习分享

在当下这个信息共享的时代,很多资源都可以在网络上找到,只取决于你愿不愿意找或是找的方法对不对了

很多朋友不是没有资料,大多都是有几十上百个G,但是杂乱无章,不知道怎么看从哪看起,甚至是看后就忘

如果大家觉得自己在网上找的资料非常杂乱、不成体系的话,我也分享一套给大家,比较系统,我平常自己也会经常研读。

2020最新上万页的大厂面试真题

七大模块学习资料:如NDK模块开发、Android框架体系架构…

只有系统,有方向的学习,才能在段时间内迅速提高自己的技术。

这份体系学习笔记,适应人群:
第一,学习知识比较碎片化,没有合理的学习路线与进阶方向。
第二,开发几年,不知道如何进阶更进一步,比较迷茫。
第三,到了合适的年纪,后续不知道该如何发展,转型管理,还是加强技术研究。如果你有需要,我这里恰好有为什么,不来领取!说不定能改变你现在的状态呢!
t_start_ms = log_contention ? MilliTime() : 0;

ArtMethod* owners_method = locking_method_;

uint32_t owners_dex_pc = locking_dex_pc_;

// Do this before releasing the lock so that we don’t get deflated.

size_t num_waiters = num_waiters_;

++num_waiters_;

monitor_lock_.Unlock(self); // Let go of locks in order.

self->SetMonitorEnterObject(GetObject());

{

ScopedThreadSuspension tsc(self, kBlocked); // Change to blocked and give up mutator_lock_.

uint32_t original_owner_thread_id = 0u;

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-c9hJ7OJU-1710704270101)]
[外链图片转存中…(img-77aycCtl-1710704270102)]
[外链图片转存中…(img-yxrlVDBt-1710704270103)]
[外链图片转存中…(img-z2xI64mJ-1710704270103)]

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
[外链图片转存中…(img-rrAnwa0J-1710704270103)]

学习分享

在当下这个信息共享的时代,很多资源都可以在网络上找到,只取决于你愿不愿意找或是找的方法对不对了

很多朋友不是没有资料,大多都是有几十上百个G,但是杂乱无章,不知道怎么看从哪看起,甚至是看后就忘

如果大家觉得自己在网上找的资料非常杂乱、不成体系的话,我也分享一套给大家,比较系统,我平常自己也会经常研读。

2020最新上万页的大厂面试真题

[外链图片转存中…(img-DgHQUahY-1710704270104)]

七大模块学习资料:如NDK模块开发、Android框架体系架构…

[外链图片转存中…(img-nemfgzk1-1710704270104)]

只有系统,有方向的学习,才能在段时间内迅速提高自己的技术。

这份体系学习笔记,适应人群:
第一,学习知识比较碎片化,没有合理的学习路线与进阶方向。
第二,开发几年,不知道如何进阶更进一步,比较迷茫。
第三,到了合适的年纪,后续不知道该如何发展,转型管理,还是加强技术研究。如果你有需要,我这里恰好有为什么,不来领取!说不定能改变你现在的状态呢!
由于文章内容比较多,篇幅不允许,部分未展示内容以截图方式展示 。如有需要获取完整的资料文档的朋友点击我的GitHub免费获取。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值