在了解了synchronized重量级锁效率特别低之后,jdk自然做了一些优化,出现了偏向锁,轻量级锁,重量级锁,自旋等优化,我们应该改正monitorenter指令就是获取对象重量级锁的错误认识,很显然,优化之后,锁的获取判断次序是偏向锁->轻量级锁->重量级锁。
偏向锁源码如下:
//偏向锁入口 void ObjectSynchronizer::fast_enter(Handle obj, BasicLock* lock, bool attempt_rebias, TRAPS) { //UseBiasedLocking判断是否开启偏向锁 if (UseBiasedLocking) { if (!SafepointSynchronize::is_at_safepoint()) { //获取偏向锁的函数调用 BiasedLocking::Condition cond = BiasedLocking::revoke_and_rebias(obj, attempt_rebias, THREAD); if (cond == BiasedLocking::BIAS_REVOKED_AND_REBIASED) { return; } } else { assert(!attempt_rebias, "can not rebias toward VM thread"); BiasedLocking::revoke_at_safepoint(obj); } } //不能偏向,就获取轻量级锁 slow_enter (obj, lock, THREAD) ; }BiasedLocking::revoke_and_rebias调用过程如下流程图:
偏向锁的撤销过程如下:
轻量级锁获取源码:
//轻量级锁入口 void ObjectSynchronizer::slow_enter(Handle obj, BasicLock* lock, TRAPS) { markOop mark = obj->mark(); //获得Mark Word assert(!mark->has_bias_pattern(), "should not see bias pattern here"); //是否无锁不可偏向,标志001 if (mark->is_neutral()) { //图A步骤1 lock->set_displaced_header(mark); //图A步骤2 if (mark == (markOop) Atomic::cmpxchg_ptr(lock, obj()->mark_addr(), mark)) { TEVENT (slow_enter: release stacklock) ; return ; } // Fall through to inflate() ... } else if (mark->has_locker() && THREAD->is_lock_owned((address)mark->locker())) { //如果Mark Word指向本地栈帧,线程重入 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);//header设置为null return; } lock->set_displace d_header(markOopDesc::unused_mark()); //轻量级锁膨胀,膨胀完成之后尝试获取重量级锁 ObjectSynchronizer::inflate(THREAD, obj())->enter(THREAD); }轻量级锁获取流程如下:
轻量级锁撤销源码:
void ObjectSynchronizer::fast_exit(oop object, BasicLock* lock, TRAPS) { assert(!object->mark()->has_bias_pattern(), "should not see bias pattern here"); markOop dhw = lock->displaced_header(); markOop mark ; if (dhw == NULL) {//如果header为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() ; } return ; } mark = object->mark() ; if (mark == (markOop) lock) { assert (dhw->is_neutral(), "invariant") ; //CAS将Mark Word内容写回 if ((markOop) Atomic::cmpxchg_ptr (dhw, object->mark_addr(), mark) == mark) { TEVENT (fast_exit: release stacklock) ; return; } } //CAS操作失败,轻量级锁膨胀,为什么在撤销锁的时候会有失败的可能? ObjectSynchronizer::inflate(THREAD, object)->exit (THREAD) ; }轻量级锁撤销流程如下:
源代码:
ObjectMonitor * ATTR ObjectSynchronizer::inflate (Thread * Self, oop object) { assert (Universe::verify_in_progress() || !SafepointSynchronize::is_at_safepoint(), "invariant") ; for (;;) { // 为后面的continue操作提供自旋 const markOop mark = object->mark() ; //获得Mark Word结构 assert (!mark->has_bias_pattern(), "invariant") ; //Mark Word可能有以下几种状态: // * Inflated(膨胀完成) - just return // * Stack-locked(轻量级锁) - coerce it to inflated // * INFLATING(膨胀中) - busy wait for conversion to complete // * Neutral(无锁) - aggressively inflate the object. // * BIASED(偏向锁) - Illegal. We should never see this 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"); //Mark->has_monitor()为true,说明已经是重量级锁了,膨胀过程已经完成,返回 return inf ; } if (mark == markOopDesc::INFLATING()) { //判断是否在膨胀 TEVENT (Inflate: spin while INFLATING) ; ReadStableMark(object) ; continue ; //如果正在膨胀,自旋等待膨胀完成 } if (mark->has_locker()) { //如果当前是轻量级锁 ObjectMonitor * m = omAlloc (Self) ;//返回一个对象的内置ObjectMonitor对象 m->Recycle(); m->_Responsible = NULL ; m->OwnerIsThread = 0 ; m->_recursions = 0 ; m->_SpinDuration = ObjectMonitor::Knob_SpinLimit ;//设置自旋获取重量级锁的次数 //CAS操作标识Mark Word正在膨胀 markOop cmp = (markOop) Atomic::cmpxchg_ptr (markOopDesc::INFLATING(), object->mark_addr(), mark) ; if (cmp != mark) { omRelease (Self, m, true) ; continue ; //如果上述CAS操作失败,自旋等待膨胀完成 } m->set_header(dmw) ; m->set_owner(mark->locker());//设置ObjectMonitor的_owner为拥有对象轻量级锁的线程,而不是当前正在inflate的线程 m->set_object(object); /** *省略了部分代码 **/ return m ; } } }轻量级锁膨胀流程图: