线程第一次拿到偏向锁,仍然是通过CAS操作拿到的?
来源:9-3 synchronized底层实现原理-2
慕哥6062902
2020-05-23
老师好,最后一分钟讲到偏向锁的优点,说加锁和解锁不需要执行CAS操作,我从其它地方了解的是说,比如第一次的时候A线程通过CAS操作拿到锁的,后面A线程重进入的时候,就不需要再次进行CAS操作了,这个时候确实是没有消耗的。想请教下到底是怎样的呢
写回答
1回答
-
翔仔
2020-05-24
同学好,第一次还是通过CAS操作拿到锁的,但是由于此时没有别的线程占用,属于第一次,基本就不没有消耗,而重入的时候,就是不需要作CAS操作
// code 3:如果锁对象的mark word的状态是偏向模式 if (mark->has_bias_pattern()) { uintptr_t thread_ident; uintptr_t anticipated_bias_locking_value; thread_ident = (uintptr_t)istate->thread(); // code 4:这里有几步操作,下文分析 anticipated_bias_locking_value = (((uintptr_t)lockee->klass()->prototype_header() | thread_ident) ^ (uintptr_t)mark) & ~((uintptr_t) markOopDesc::age_mask_in_place); // code 5:如果偏向的线程是自己且epoch等于class的epoch if (anticipated_bias_locking_value == 0) { // already biased towards this thread, nothing to do if (PrintBiasedLockingStatistics) { (* BiasedLocking::biased_lock_entry_count_addr())++; } success = true; } // code 6:如果偏向模式关闭,则尝试撤销偏向锁 else if ((anticipated_bias_locking_value & markOopDesc::biased_lock_mask_in_place) != 0) { markOop header = lockee->klass()->prototype_header(); if (hash != markOopDesc::no_hash) { header = header->copy_set_hash(hash); } // 利用CAS操作将mark word替换为class中的mark word if (Atomic::cmpxchg_ptr(header, lockee->mark_addr(), mark) == mark) { if (PrintBiasedLockingStatistics) (*BiasedLocking::revoked_lock_entry_count_addr())++; } } // code 7:如果epoch不等于class中的epoch,则尝试重偏向 else if ((anticipated_bias_locking_value & epoch_mask_in_place) !=0) { // 构造一个偏向当前线程的mark word markOop new_header = (markOop) ( (intptr_t) lockee->klass()->prototype_header() | thread_ident); if (hash != markOopDesc::no_hash) { new_header = new_header->copy_set_hash(hash); } // CAS替换对象头的mark word if (Atomic::cmpxchg_ptr((void*)new_header, lockee->mark_addr(), mark) == mark) { if (PrintBiasedLockingStatistics) (* BiasedLocking::rebiased_lock_entry_count_addr())++; } else { // 重偏向失败,代表存在多线程竞争,则调用monitorenter方法进行锁升级 CALL_VM(InterpreterRuntime::monitorenter(THREAD, entry), handle_exception); } success = true; } else { // 走到这里说明当前要么偏向别的线程,要么是匿名偏向(即没有偏向任何线程) // code 8:下面构建一个匿名偏向的mark word,尝试用CAS指令替换掉锁对象的mark word markOop header = (markOop) ((uintptr_t) mark & ((uintptr_t)markOopDesc::biased_lock_mask_in_place |(uintptr_t)markOopDesc::age_mask_in_place |epoch_mask_in_place)); if (hash != markOopDesc::no_hash) { header = header->copy_set_hash(hash); } markOop new_header = (markOop) ((uintptr_t) header | thread_ident); // debugging hint DEBUG_ONLY(entry->lock()->set_displaced_header((markOop) (uintptr_t) 0xdeaddead);) if (Atomic::cmpxchg_ptr((void*)new_header, lockee->mark_addr(), header) == header) { // CAS修改成功 if (PrintBiasedLockingStatistics) (* BiasedLocking::anonymously_biased_lock_entry_count_addr())++; } else { // 如果修改失败说明存在多线程竞争,所以进入monitorenter方法 CALL_VM(InterpreterRuntime::monitorenter(THREAD, entry), handle_exception); } success = true; }
132021-12-07
相似问题