您的位置:首页 > 保险 > 正文

今日讯!深入浅出synchronized的原理与源码

2023-06-29 06:40:37 来源:博客园


(资料图)

深入浅出synchronized的原理与源码1.java对象头关于锁的标识1.对象头
//  32 bits://  --------//             hash:25 ------------>| age:4    biased_lock:1 lock:2 (normal object)//             JavaThread*:23 epoch:2 age:4    biased_lock:1 lock:2 (biased object)//             size:32 ------------------------------------------>| (CMS free block)//             PromotedObject*:29 ---------->| promo_bits:3 ----->| (CMS promoted object)////  64 bits://  --------//  unused:25 hash:31 -->| unused:1   age:4    biased_lock:1 lock:2 (normal object)//  JavaThread*:54 epoch:2 unused:1   age:4    biased_lock:1 lock:2 (biased object)//  PromotedObject*:61 --------------------->| promo_bits:3 ----->| (CMS promoted object)//  size:64 ----------------------------------------------------->| (CMS free block)////  unused:25 hash:31 -->| cms_free:1 age:4    biased_lock:1 lock:2 (COOPs && normal object)//  JavaThread*:54 epoch:2 cms_free:1 age:4    biased_lock:1 lock:2 (COOPs && biased object)//  narrowOop:32 unused:24 cms_free:1 unused:4 promo_bits:3 ----->| (COOPs && CMS promoted object)//  unused:21 size:35 -->| cms_free:1 unused:7 ------------------>| (COOPs && CMS free block)//    [JavaThread* | epoch | age | 1 | 01]       lock is biased toward given thread//    [0           | epoch | age | 1 | 01]       lock is anonymously biased////  - the two lock bits are used to describe three states: locked/unlocked and monitor.////    [ptr             | 00]  locked             ptr points to real header on stack//    [header      | 0 | 01]  unlocked           regular object header//    [ptr             | 10]  monitor            inflated lock (header is wapped out)//    [ptr             | 11]  marked             used by markSweep to mark an object//                                               not valid at any other time
2.java中synchronized的字节码表示

在java中使用synchronized会在字节码层面生成monitorenter和_monitorexit。这是一个上锁和解锁的过程保证原子性的操作。

3.monitorenter的流程图4.moniterexit的流程图2.JVM源码bytecodeInterpreter.cpp中的_monitorenter
CASE(_monitorenter): {        oop lockee = STACK_OBJECT(-1);//从操作数栈上获取锁对象        // derefing"s lockee ought to provoke implicit null check        CHECK_NULL(lockee);//判空操作        // find a free monitor or one already allocated for this object        // if we find a matching object then we need a new monitor        // since this is recursive enter        BasicObjectLock* limit = istate->monitor_base();        BasicObjectLock* most_recent = (BasicObjectLock*) istate->stack_base();        BasicObjectLock* entry = NULL;        while (most_recent != limit ) {//从线程栈上找到一个锁对象为空的对象          if (most_recent->obj() == NULL) entry = most_recent;          else if (most_recent->obj() == lockee) break;//如果当前的锁对象时lockee直接返回          most_recent++;        }        if (entry != NULL) {//entry不为空表示有BasicObjectLock,有锁对象可以获取          entry->set_obj(lockee);//设置当前锁对象为lockee          int success = false;          uintptr_t epoch_mask_in_place = (uintptr_t)markOopDesc::epoch_mask_in_place;//获取epoch的值          markOop mark = lockee->mark();//获取锁对象头部          intptr_t hash = (intptr_t) markOopDesc::no_hash;//获取原始的hash值          // implies UseBiasedLocking          if (mark->has_bias_pattern()) {//判断是否有偏向锁            uintptr_t thread_ident;            uintptr_t anticipated_bias_locking_value;            thread_ident = (uintptr_t)istate->thread();//获取线程标识            anticipated_bias_locking_value =              (((uintptr_t)lockee->klass()->prototype_header() | thread_ident) ^ (uintptr_t)mark) &              ~((uintptr_t) markOopDesc::age_mask_in_place);// 获取原始对象头部 组合 上当前线程地址信息,与当前对象做对比(异或运算,相同为 0,相异为 1,运算后保留为 1 的位也即不同位),随后 与 对象年龄位的相反值做与运算(与运算等价于二进制截断,混沌学堂中说过哈),等价于 :将当前对象头部相对于原始对象头部不同的位,去掉年龄位,得到anticipated_bias_locking_value             if  (anticipated_bias_locking_value == 0) {//表示除年龄代外,没有差异,当前偏向锁已经偏向当前线程              // already biased towards this thread, nothing to do              if (PrintBiasedLockingStatistics) {                (* BiasedLocking::biased_lock_entry_count_addr())++;              }              success = true;            }            else if ((anticipated_bias_locking_value & markOopDesc::biased_lock_mask_in_place) != 0) {//如果当前持有偏向锁,尝试撤销偏向锁              // try revoke bias              markOop header = lockee->klass()->prototype_header();//找到原型头部              if (hash != markOopDesc::no_hash) {//如果hash值不同                header = header->copy_set_hash(hash);//头部设置hash值              }              if (lockee->cas_set_mark(header, mark) == mark) {//cas将当前锁的头部替换为原型头部,也即尝试撤销偏向锁                if (PrintBiasedLockingStatistics)                  (*BiasedLocking::revoked_lock_entry_count_addr())++;              }            }            else if ((anticipated_bias_locking_value & epoch_mask_in_place) !=0) {//如果当前头部已经发生变化,并且epoch不为0,表示已经滚动过,尝试重偏向。这里表示发生过批量锁撤销              // try rebias              markOop new_header = (markOop) ( (intptr_t) lockee->klass()->prototype_header() | thread_ident);//获取到当前线程的原型头部              if (hash != markOopDesc::no_hash) {//hash值不同设置hash值                new_header = new_header->copy_set_hash(hash);              }              if (lockee->cas_set_mark(new_header, mark) == mark) {//cas将当前头部替换为新头部,也即尝试冲片向                if (PrintBiasedLockingStatistics)                  (* BiasedLocking::rebiased_lock_entry_count_addr())++;              }              else {//cas失败,进入monitorenter.                CALL_VM(InterpreterRuntime::monitorenter(THREAD, entry), handle_exception);              }              success = true;            }            else {              //在这里是处理,偏向锁标识已经打开,但是并没有偏向锁并没有偏向某个线程、              // try to bias towards thread in case object is anonymously biased              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));//// 因为 匿名偏向锁 中保存着 当前对象头的头部信息(年龄、epoch)所以需要保留下来                              if (hash != markOopDesc::no_hash) {///hash值不同设置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 (lockee->cas_set_mark(new_header, header) == header) {//cas将头部替换为new_header,偏向当前线程                if (PrintBiasedLockingStatistics)                  (* BiasedLocking::anonymously_biased_lock_entry_count_addr())++;              }              else {//cas失败进入monitorenter                CALL_VM(InterpreterRuntime::monitorenter(THREAD, entry), handle_exception);              }              success = true;            }          }          // traditional lightweight locking          if (!success) {//偏向锁获取失败            markOop displaced = lockee->mark()->set_unlocked();//将当前头部设置为无锁            entry->lock()->set_displaced_header(displaced);//替换当前头部            bool call_vm = UseHeavyMonitors;//默认是false            if (call_vm || lockee->cas_set_mark((markOop)entry, displaced) != displaced) {//cas将当前头部替换为entry,也即轻量级锁              // Is it simple recursive case?              if (!call_vm && THREAD->is_lock_owned((address) displaced->clear_lock_bits())) {//判断当前线程是否就是上锁的线程                entry->lock()->set_displaced_header(NULL);//锁重入,将当前lock的头部置为空              } else {//否则头部替换失败,进入monitorenter                CALL_VM(InterpreterRuntime::monitorenter(THREAD, entry), handle_exception);              }            }          }          UPDATE_PC_AND_TOS_AND_CONTINUE(1, -1);        } else {          istate->set_msg(more_monitors);//当前没有锁对象,set_msg,提示需要更多的监视器对象          UPDATE_PC_AND_RETURN(0); // Re-execute        }      }
InterpreterRuntime::monitorenter
IRT_ENTRY_NO_ASYNC(void, InterpreterRuntime::monitorenter(JavaThread* thread, BasicObjectLock* elem))  Handle h_obj(thread, elem->obj());  assert(Universe::heap()->is_in_reserved_or_null(h_obj()),         "must be NULL or an object");  if (UseBiasedLocking) {//如果持有偏向锁    // Retry fast entry if bias is revoked to avoid unnecessary inflation    ObjectSynchronizer::fast_enter(h_obj, elem->lock(), true, CHECK);  } else {//否则直接执行slow_enter锁升级    ObjectSynchronizer::slow_enter(h_obj, elem->lock(), CHECK);  }IRT_END
ObjectSynchronizer::fast_enter
void ObjectSynchronizer::fast_enter(Handle obj, BasicLock* lock,                                    bool attempt_rebias, TRAPS) {  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);//在线程安全点进行撤销    }    assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");  }  slow_enter(obj, lock, THREAD);//进入锁升级过程}
BiasedLocking::revoke_and_rebias
BiasedLocking::Condition BiasedLocking::revoke_and_rebias(Handle obj, bool attempt_rebias, TRAPS) {  // We can revoke the biases of anonymously-biased objects  // efficiently enough that we should not cause these revocations to  // update the heuristics because doing so may cause unwanted bulk  // revocations (which are expensive) to occur.  markOop mark = obj->mark();//获取当前头部  if (mark->is_biased_anonymously() && !attempt_rebias) {//如果头部是匿名偏向锁,并且不允许重偏向    // We are probably trying to revoke the bias of this object due to    // an identity hash code computation. Try to revoke the bias    // without a safepoint. This is possible if we can successfully    // compare-and-exchange an unbiased header into the mark word of    // the object, meaning that no other thread has raced to acquire    // the bias of the object.    markOop biased_value       = mark;    markOop unbiased_prototype = markOopDesc::prototype()->set_age(mark->age());//获取没有偏向锁的原型头部    markOop res_mark = obj->cas_set_mark(unbiased_prototype, mark);//cas设置mark头部的值    if (res_mark == biased_value) {//cas成功,标识锁撤销      return BIAS_REVOKED;//返回BIAS_REVOKED    }  } else if (mark->has_bias_pattern()) {//如果当前是偏向锁    Klass* k = obj->klass();//获取原始类对象    markOop prototype_header = k->prototype_header();//获取原始头部    if (!prototype_header->has_bias_pattern()) {//如果原始头部无偏向锁      // This object has a stale bias from before the bulk revocation      // for this data type occurred. It"s pointless to update the      // heuristics at this point so simply update the header with a      // CAS. If we fail this race, the object"s bias has been revoked      // by another thread so we simply return and let the caller deal      // with it.      markOop biased_value       = mark;      markOop res_mark = obj->cas_set_mark(prototype_header, mark);//cas替换头部,撤销偏向锁      assert(!obj->mark()->has_bias_pattern(), "even if we raced, should still be revoked");      return BIAS_REVOKED;//返回BIAS_REVOKED    } else if (prototype_header->bias_epoch() != mark->bias_epoch()) {//如果原始头部的epoch与当前头部的epoch不同,表示滚动或当前轮次。      // The epoch of this biasing has expired indicating that the      // object is effectively unbiased. Depending on whether we need      // to rebias or revoke the bias of this object we can do it      // efficiently enough with a CAS that we shouldn"t update the      // heuristics. This is normally done in the assembly code but we      // can reach this point due to various points in the runtime      // needing to revoke biases.      if (attempt_rebias) {//是否允许重偏向        assert(THREAD->is_Java_thread(), "");        markOop biased_value       = mark;        markOop rebiased_prototype = markOopDesc::encode((JavaThread*) THREAD, mark->age(), prototype_header->bias_epoch());//重偏向头部组装        markOop res_mark = obj->cas_set_mark(rebiased_prototype, mark);//cas设置mark值,成功表示重偏向成功        if (res_mark == biased_value) {//相等,表示撤销重偏向成功          return BIAS_REVOKED_AND_REBIASED;//返回:BIAS_REVOKED_AND_REBIASED        }      } else {//不允许重偏向,直接撤销偏向锁        markOop biased_value       = mark;        markOop unbiased_prototype = markOopDesc::prototype()->set_age(mark->age());        markOop res_mark = obj->cas_set_mark(unbiased_prototype, mark);        if (res_mark == biased_value) {          return BIAS_REVOKED;        }      }    }  }
BiasedLocking::revoke_at_safepoint
void BiasedLocking::revoke_at_safepoint(Handle h_obj) {  oop obj = h_obj();  HeuristicsResult heuristics = update_heuristics(obj, false);  if (heuristics == HR_SINGLE_REVOKE) {//如果是HR_SINGLE_REVOKE,表示单个偏向锁撤销    revoke_bias(obj, false, false, NULL, NULL);  } else if ((heuristics == HR_BULK_REBIAS) ||             (heuristics == HR_BULK_REVOKE)) {//HR_BULK_REBIAS,HR_BULK_REVOKE表示批量的操作。    bulk_revoke_or_rebias_at_safepoint(obj, (heuristics == HR_BULK_REBIAS), false, NULL);//批量的操作需要在线程安全点,进行批量操作  }  clean_up_cached_monitor_info();//清楚缓存的监视器信息}
HeuristicsResult::update_heuristics
static HeuristicsResult update_heuristics(oop o, bool allow_rebias) {  markOop mark = o->mark();//获取头部mark  if (!mark->has_bias_pattern()) {//如果不是偏向锁直接返回    return HR_NOT_BIASED;  }  // Heuristics to attempt to throttle the number of revocations.  // Stages:  // 1. Revoke the biases of all objects in the heap of this type,  //    but allow rebiasing of those objects if unlocked.  // 2. Revoke the biases of all objects in the heap of this type  //    and don"t allow rebiasing of these objects. Disable  //    allocation of objects of that type with the bias bit set.  Klass* k = o->klass();//获取类元数据对象  jlong cur_time = os::javaTimeMillis();  jlong last_bulk_revocation_time = k->last_biased_lock_bulk_revocation_time();//获取上一次批量撤销的时间  int revocation_count = k->biased_lock_revocation_count();//获取偏向锁撤销的次数  if ((revocation_count >= BiasedLockingBulkRebiasThreshold) &&//撤销的次数大于批量重偏向的阈值 BiasedLockingBulkRebiasThreshold, 20      (revocation_count <  BiasedLockingBulkRevokeThreshold) &&//撤销的次数小于于批量撤销的阈值 BiasedLockingBulkRevokeThreshold, 40      (last_bulk_revocation_time != 0) &&//上一次批量撤销的时间不为0      (cur_time - last_bulk_revocation_time >= BiasedLockingDecayTime)) {//当前时间-上一次批量撤销的时间是否大于BiasedLockingDecayTime, 25000。大于这个时间,标识当前这个批量撤销,已经腐朽无效了,直接重置    // This is the first revocation we"ve seen in a while of an    // object of this type since the last time we performed a bulk    // rebiasing operation. The application is allocating objects in    // bulk which are biased toward a thread and then handing them    // off to another thread. We can cope with this allocation    // pattern via the bulk rebiasing mechanism so we reset the    // klass"s revocation count rather than allow it to increase    // monotonically. If we see the need to perform another bulk    // rebias operation later, we will, and if subsequently we see    // many more revocation operations in a short period of time we    // will completely disable biasing for this type.    k->set_biased_lock_revocation_count(0);//将偏向锁撤销次数置为0    revocation_count = 0;  }  // Make revocation count saturate just beyond BiasedLockingBulkRevokeThreshold  if (revocation_count <= BiasedLockingBulkRevokeThreshold) {//如果撤销的次数小于等于批量锁撤销的阈值    revocation_count = k->atomic_incr_biased_lock_revocation_count();//增加锁撤销的次数  }  if (revocation_count == BiasedLockingBulkRevokeThreshold) {//如果撤销的次数等于批量锁撤销的阈值    return HR_BULK_REVOKE;//返回HR_BULK_REVOKE,表示批量锁撤销  }  if (revocation_count == BiasedLockingBulkRebiasThreshold) {//如果撤销的次数等于批量重偏向的阈值    return HR_BULK_REBIAS;//HR_BULK_REBIAS,表示批量重偏向  }  return HR_SINGLE_REVOKE;//否则返回HR_SINGLE_REVOKE,表示只撤销单个}
bulk_revoke_or_rebias_at_safepoint
static BiasedLocking::Condition bulk_revoke_or_rebias_at_safepoint(oop o,                                                                   bool bulk_rebias,                                                                   bool attempt_rebias_of_object,                                                                   JavaThread* requesting_thread) {  jlong cur_time = os::javaTimeMillis();//获取当前时间  o->klass()->set_last_biased_lock_bulk_revocation_time(cur_time);//设置批量锁操作的时间  Klass* k_o = o->klass();//获取类的元数据信息  Klass* klass = k_o;  {    JavaThreadIteratorWithHandle jtiwh;    if (bulk_rebias) {//如果是批量重偏向      if (klass->prototype_header()->has_bias_pattern()) {//判断当前原型头部是否有偏向锁位        int prev_epoch = klass->prototype_header()->bias_epoch();//获取当前偏向锁的轮次        klass->set_prototype_header(klass->prototype_header()->incr_bias_epoch());//增加偏向锁的轮次        int cur_epoch = klass->prototype_header()->bias_epoch();        // Now walk all threads" stacks and adjust epochs of any biased        // and locked objects of this data type we encounter        for (; JavaThread *thr = jtiwh.next(); ) {          GrowableArray* cached_monitor_info = get_or_compute_monitor_info(thr);//获取当前线程栈的锁信息          for (int i = 0; i < cached_monitor_info->length(); i++) {//遍历线程栈的锁信息            MonitorInfo* mon_info = cached_monitor_info->at(i);            oop owner = mon_info->owner();            markOop mark = owner->mark();            if ((owner->klass() == k_o) && mark->has_bias_pattern()) {//如果锁对象等于k_0对象并且有偏向锁              // We might have encountered this object already in the case of recursive locking              owner->set_mark(mark->set_bias_epoch(cur_epoch));//设置头部的epoch轮次            }          }        }      }      // At this point we"re done. All we have to do is potentially      // adjust the header of the given object to revoke its bias.      revoke_bias(o, attempt_rebias_of_object && klass->prototype_header()->has_bias_pattern(), true, requesting_thread, NULL);//撤销偏向锁    } else {//否则不是批量重偏向      if (log_is_enabled(Info, biasedlocking)) {        ResourceMark rm;        log_info(biasedlocking)("* Disabling biased locking for type %s", klass->external_name());      }      // Disable biased locking for this data type. Not only will this      // cause future instances to not be biased, but existing biased      // instances will notice that this implicitly caused their biases      // to be revoked.      klass->set_prototype_header(markOopDesc::prototype());//设置原型头部。所有的对象都依赖于一个元数据类,所以只需要设置原型头部      // Now walk all threads" stacks and forcibly revoke the biases of      // any locked and biased objects of this data type we encounter.      for (; JavaThread *thr = jtiwh.next(); ) {        GrowableArray* cached_monitor_info = get_or_compute_monitor_info(thr);        for (int i = 0; i < cached_monitor_info->length(); i++) {          MonitorInfo* mon_info = cached_monitor_info->at(i);          oop owner = mon_info->owner();          markOop mark = owner->mark();          if ((owner->klass() == k_o) && mark->has_bias_pattern()) {//当前监视器的拥有者对象等于k_o,并且有偏向锁            revoke_bias(owner, false, true, requesting_thread, NULL);//批量锁撤销          }        }      }      // Must force the bias of the passed object to be forcibly revoked      // as well to ensure guarantees to callers      revoke_bias(o, false, true, requesting_thread, NULL);//批量锁撤销或者锁撤销    }  } // ThreadsListHandle is destroyed here.  BiasedLocking::Condition status_code = BiasedLocking::BIAS_REVOKED;  if (attempt_rebias_of_object &&//如果允许重偏向,重偏向到requesting_thread线程      o->mark()->has_bias_pattern() &&//mark头部标识有锁      klass->prototype_header()->has_bias_pattern()) {//原型头部也标识有锁    markOop new_mark = markOopDesc::encode(requesting_thread, o->mark()->age(),                                           klass->prototype_header()->bias_epoch());//重组头部    o->set_mark(new_mark);//设置对象头部    status_code = BiasedLocking::BIAS_REVOKED_AND_REBIASED;//设置状态信息    log_info(biasedlocking)("  Rebiased object toward thread " INTPTR_FORMAT, (intptr_t) requesting_thread);  }  return status_code;//返回状态信息}
BiasedLocking::Condition revoke_bias
// After the call, *biased_locker will be set to obj->mark()->biased_locker() if biased_locker != NULL,// AND it is a living thread. Otherwise it will not be updated, (i.e. the caller is responsible for initialization).static BiasedLocking::Condition revoke_bias(oop obj, bool allow_rebias, bool is_bulk, JavaThread* requesting_thread, JavaThread** biased_locker) {  markOop mark = obj->mark();//获取对象mark头部  if (!mark->has_bias_pattern()) {//没有头部直接返回    return BiasedLocking::NOT_BIASED;  }  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) {//线程为空    // Object is anonymously biased. We can get here if, for    // example, we revoke the bias due to an identity hash code    // being computed for an object.    if (!allow_rebias) {//判断允许重偏向      obj->set_mark(unbiased_prototype);//设置mark头部为没有偏向锁的头部    }    return BiasedLocking::BIAS_REVOKED;//返回偏向锁撤销  }  // Handle case where the thread toward which the object was biased has exited  bool thread_is_alive = false;//线程是否存活标识  if (requesting_thread == biased_thread) {//requesting_thread线程是偏向锁线程    thread_is_alive = true;  } else {    ThreadsListHandle tlh;    thread_is_alive = tlh.includes(biased_thread);//遍历判断线程是否存活  }  if (!thread_is_alive) {//线程已经不是存活状态    if (allow_rebias) {//允许重偏向      obj->set_mark(biased_prototype);//设置mark为偏向锁的原型头部    } else {      obj->set_mark(unbiased_prototype);//设置mark为不持有偏向锁的原型头部    }    return BiasedLocking::BIAS_REVOKED;//返回状态BIAS_REVOKED,表示偏向锁撤销  }  // Thread owning bias is alive.  // Check to see whether it currently owns the lock and, if so,  // write down the needed displaced headers to the thread"s stack.  // Otherwise, restore the object"s header either to the unlocked  // or unbiased state.   //// 持有偏向锁的线程仍旧存活,那么遍历它的线程栈的锁信息(这里为 锁重入场景,因为锁重入会创建多个 BasicObjectLock 信息),将当前锁对象的 BasicLock 的替换头部信息设置为不存在偏向锁的对象头部  GrowableArray* 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);    if (oopDesc::equals(mon_info->owner(), obj)) {//如果监视器对象的拥有者是obj      // Assume recursive case and fix up highest lock later      markOop mark = markOopDesc::encode((BasicLock*) NULL);//设置mark为null      highest_lock = mon_info->lock();      highest_lock->set_displaced_header(mark);//将为空的mark设置到头部中    } else {      log_trace(biasedlocking)("   mon_info->owner (" PTR_FORMAT ") != obj (" PTR_FORMAT ")",                               p2i((void *) mon_info->owner()),                               p2i((void *) obj));    }  }  //// 最高位的锁为锁重入的最后一把锁,所以需要将锁替换后的头部修正为不开启偏向锁的头部,且将对象的头部还原为指向 该线程的最高位锁:BasicLock。此时,等价于将偏向锁升级为了 轻量级锁状态:对象头部的 mark 指针指向 线程栈上的 BasicObjectLock 而不是 线程 ID  if (highest_lock != NULL) {//表示锁重入的最后一把锁    // Fix up highest lock to contain displaced header and point    // object at it    highest_lock->set_displaced_header(unbiased_prototype);//将highest_lock头部设置为没有偏向锁的原型头部    // Reset object header to point to displaced mark.    // Must release storing the lock address for platforms without TSO    // ordering (e.g. ppc).    obj->release_set_mark(markOopDesc::encode(highest_lock));//将当前持有锁的ob对象的头部锁释放  } else {    if (allow_rebias) {//如果允许重偏向      obj->set_mark(biased_prototype);//直接将obj设置为biased_prototype,偏向锁的原型头部    } else {      // Store the unlocked value into the object"s header.      obj->set_mark(unbiased_prototype);//直接将obj设置为biased_prototype,没有偏向锁的原型头部    }  }  // If requested, return information on which thread held the bias  if (biased_locker != NULL) {    *biased_locker = biased_thread;  }  return BiasedLocking::BIAS_REVOKED;//返回BIAS_REVOKED}
ObjectSynchronizer::slow_enter
void ObjectSynchronizer::slow_enter(Handle obj, BasicLock* lock, TRAPS) {  markOop mark = obj->mark();//对象头部  if (mark->is_neutral()) {//mark是否是无锁    // Anticipate successful CAS -- the ST of the displaced mark must    // be visible <= the ST performed by the CAS.    lock->set_displaced_header(mark);//设置lock的头部    if (mark == obj()->cas_set_mark((markOop) lock, mark)) {//cas将锁对象设置为lock。      return;返回    }    // Fall through to inflate() ...  } else if (mark->has_locker() &&//mark当前头部有锁             THREAD->is_lock_owned((address)mark->locker())) {//当前线程是否是锁的拥有者    lock->set_displaced_header(NULL);//锁重入    return;  }  // The object header will never be displaced to this lock,  // so it does not matter what the value is, except that it  // must be non-zero to avoid looking like a re-entrant lock,  // and must not look locked either.  lock->set_displaced_header(markOopDesc::unused_mark());//将头部设置未使用标识  //锁膨胀  ObjectSynchronizer::inflate(THREAD,                              obj(),                              inflate_cause_monitor_enter)->enter(THREAD);}
ObjectSynchronizer::inflate
ObjectMonitor* ObjectSynchronizer::inflate(Thread * Self,                                                     oop object,                                                     const InflateCause cause) {  EventJavaMonitorInflate event;  for (;;) {    const markOop mark = object->mark();//获取对象头部    assert(!mark->has_bias_pattern(), "invariant");    // The mark can be in one of the following states:    // *  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    // CASE: inflated    if (mark->has_monitor()) {//如果当前mark对象已经有了monitor,也即有了重量级锁      ObjectMonitor * inf = mark->monitor();//获得monitor对象      return inf;//直接返回    }    if (mark == markOopDesc::INFLATING()) {//如果当前对象在锁膨胀过程中      ReadStableMark(object);//读取最新头部mark      continue;    }    if (mark->has_locker()) {//如果当前有锁,标识持有      ObjectMonitor * m = omAlloc(Self);//获取一个ObjectMonitor对象      // Optimistically prepare the objectmonitor - anticipate successful CAS      // We do this before the CAS in order to minimize the length of time      // in which INFLATING appears in the mark.      m->Recycle();      m->_Responsible  = NULL;//Reponsible的作用:优化操作当nxt==null或者_EntryList为空,标识后续没有需要等待的线程,将自身作为头结点,去睡眠一秒钟后,醒过来直接获得锁继续执行,而不是等待唤醒,提升性能。      m->_recursions   = 0;      m->_SpinDuration = ObjectMonitor::Knob_SpinLimit;   // Consider: maintain by type/class      markOop cmp = object->cas_set_mark(markOopDesc::INFLATING(), mark);//cas将头部状态进行替换      if (cmp != mark) {//cas失败,继续尝试        omRelease(Self, m, true);//释放监视器对象        continue;       // Interference -- just retry      }              //// 若执行到这里,那么当前线程负责所膨胀,只需要将对象原始的头部放置在 ObjectMonitor 中,但这里需要注意的是:由于轻量级锁仍然被其他线程所持有,所以这里 ObjectMonitor 的 owner 为 BasicObjectLock 而不是线程      markOop dmw = mark->displaced_mark_helper();//获取轻量级锁的头部      // Setup monitor fields to proper values -- prepare the monitor      m->set_header(dmw);//设置头部为dmw      m->set_owner(mark->locker());//将当前monitor拥有者设置为轻量级锁的对象      m->set_object(object);//设置对象为object      object->release_set_mark(markOopDesc::encode(m));//将对象头部设置为监视器头部      return m;//返回对象    }    //对象的提前初始化    ObjectMonitor * m = omAlloc(Self);    // prepare m for installation - set monitor to initial state    m->Recycle();    m->set_header(mark);    m->set_owner(NULL);    m->set_object(object);    m->_recursions   = 0;    m->_Responsible  = NULL;    m->_SpinDuration = ObjectMonitor::Knob_SpinLimit;       // consider: keep metastats by type/class    if (object->cas_set_mark(markOopDesc::encode(m), mark) != mark) {//尝试cas将object的头部mark置为ObjectMonitor对象      //cas失败,参数还原继续尝试      m->set_object(NULL);//      m->set_owner(NULL);      m->Recycle();      omRelease(Self, m, true);      m = NULL;      continue;    }    return m;//返回监视器对象m  }}
ObjectMonitor::enter
void ObjectMonitor::enter(TRAPS) {  Thread * const Self = THREAD;//获取线程对象  void * cur = Atomic::cmpxchg(Self, &_owner, (void*)NULL);//  CAS 尝试将当前线程设置为 owner,若设置成功,表明当前线程获取了该监视器锁。注意:该方法若成功,那么将会返回比较值 null,若失败将返回 _owner 最新值(参考并发专题的描述)  if (cur == NULL) {// 比较成功,则返回比较值 null,说明当前线程抢到了锁,直接返回    return;  }  if (cur == Self) {// 比较失败,返回当前最新值,表明当前线程锁重入,增加重入次数即可    _recursions++;//锁重入    return;  }  if (Self->is_lock_owned ((address)cur)) {// 当前线程之前已经获取到轻量级锁,然后执行业务,其他线程无法获取锁,从而将其升级到重量级锁,而当前线程在持有轻量级锁后,又重复获取锁,那么此时只需要将 重入次数和 owner修改即可    assert(_recursions == 0, "internal state error");    _recursions = 1;    _owner = Self;    return;  }  Self->_Stalled = intptr_t(this);// 设置当前线程阻塞在该 ObjectMonitor上  if (TrySpin(Self) > 0) {//尝试自旋获取锁    Self->_Stalled = 0;//获取成功置为0    return;//返回  }  JavaThread * jt = (JavaThread *) Self;//获取当前线程java的线程对象  // Prevent deflation at STW-time.  See deflate_idle_monitors() and is_busy().  // Ensure the object-monitor relationship remains stable while there"s contention.  Atomic::inc(&_count);//引用计数加1  JFR_ONLY(JfrConditionalFlushWithStacktrace flush(jt);)  EventJavaMonitorEnter event;  if (event.should_commit()) {    event.set_monitorClass(((oop)this->object())->klass());    event.set_address((uintptr_t)(this->object_addr()));  }  { // Change java thread status to indicate blocked on monitor enter.    JavaThreadBlockedOnMonitorEnterState jtbmes(jt, this);    Self->set_current_pending_monitor(this);//标识当前线程阻塞在当前objectMonitor上    for (;;) {           EnterI(THREAD);//完成获取锁的流程      //获取成功后参数置位      _recursions = 0;      _succ = NULL;      exit(false, Self);      jt->java_suspend_self();    }  }  Atomic::dec(&_count);//引用计数减1  Self->_Stalled = 0;}
ObjectMonitor::EnterI
void ObjectMonitor::EnterI(TRAPS) {  Thread * const Self = THREAD;//获取当前线程对象  // Try the lock - TATAS  if (TryLock (Self) > 0) {//cas自旋抢锁。成功直接返回    return;  }   if (TrySpin(Self) > 0) {//尝试自旋,中间如果抢到锁,直接返回    return;  }  //参数初始化    ObjectWaiter node(Self);//新建等待节点  Self->_ParkEvent->reset();//重置parkEvent  node._prev   = (ObjectWaiter *) 0xBAD;  node.TState  = ObjectWaiter::TS_CXQ;  ObjectWaiter * nxt;    //头插法,插入成功直接退出。  for (;;) {    node._next = nxt = _cxq;    if (Atomic::cmpxchg(&node, &_cxq, nxt) == nxt) break;    //尝试继续抢锁,抢到直接返回    if (TryLock (Self) > 0) {      return;    }  }  //如果nxt = _cxq队列和_EntryList队列都为空  if (nxt == NULL && _EntryList == NULL) {    // Try to assume the role of responsible thread for the monitor.    // CONSIDER:  ST vs CAS vs { if (Responsible==null) Responsible=Self }    Atomic::replace_if_null(Self, &_Responsible);//如果_Responsible为空的话,赋值为Self  }  int nWakeups = 0;  int recheckInterval = 1;  for (;;) {    if (TryLock(Self) > 0) break;//抢锁成功直接返回    // park self    if (_Responsible == Self) {//如果_Responsible是当前Self,_Responsible属于优化操作,不让线程直接取阻塞等待唤醒,而是超时等待,过了一定时间自己醒过来去获取锁      Self->_ParkEvent->park((jlong) recheckInterval);//进行超时等待      // Increase the recheckInterval, but clamp the value.      recheckInterval *= 8;      if (recheckInterval > MAX_RECHECK_INTERVAL) {//MAX_RECHECK_INTERVAL 1000        recheckInterval = MAX_RECHECK_INTERVAL;      }    } else {      Self->_ParkEvent->park();//进行阻塞等待    }    if (TryLock(Self) > 0) break;//获得锁,直接返回    OM_PERFDATA_OP(FutileWakeups, inc());    ++nWakeups;    if (TrySpin(Self) > 0) break;//尝试自旋,获得锁直接返回    if (_succ == Self) _succ = NULL;//获得锁了,需要将_succ置为空    OrderAccess::fence();//全屏障,保证上述操作的变量,下面的流程都可以获取到最新值  }  UnlinkAfterAcquire(Self, &node);//进行断链  if (_succ == Self) _succ = NULL;  if (_Responsible == Self) {    _Responsible = NULL;    OrderAccess::fence(); // Dekker pivot-point  }  return;}
ObjectMonitor::TryLock
int ObjectMonitor::TryLock(Thread * Self) {  void * own = _owner;//获取锁的拥有者  if (own != NULL) return 0;//如果有其他线程已经获得锁,直接返回  if (Atomic::replace_if_null(Self, &_owner)) {//原子性操作,设置_owner为Self也即当前线程,设置成功    // Either guarantee _recursions == 0 or set _recursions = 0.    return 1;//返回1,表示获取锁成功  }  // The lock had been free momentarily, but we lost the race to the lock.  // Interference -- the CAS failed.  // We can either return -1 or retry.  // Retry doesn"t make as much sense because the lock was just acquired.  return -1;}
ObjectMonitor::TrySpin
int ObjectMonitor::TrySpin(Thread * Self) {  int ctr = Knob_FixedSpin;//Knob_FixedSpin           = 0;  if (ctr != 0) {//如果ctr不等于0,尝试自旋获得锁    while (--ctr >= 0) {      if (TryLock(Self) > 0) return 1;      SpinPause();    }    return 0;  }  //for循环等待,并尝试获得锁  for (ctr = Knob_PreSpin + 1; --ctr >= 0;) {// Knob_PreSpin= 10;// 20-100 likely better    if (TryLock(Self) > 0) {//尝试获取锁      int x = _SpinDuration;//初始值为0      if (x < Knob_SpinLimit) {//ObjectMonitor::Knob_SpinLimit = 5000;        if (x < Knob_Poverty) x = Knob_Poverty;//Knob_Poverty = 1000;        _SpinDuration = x + Knob_BonusB;      }      return 1;    }    SpinPause();  }  //这里表示自旋过程中并没有获得锁  ctr = _SpinDuration;  if (ctr <= 0) return 0;  //线程不是可执行状态  if (NotRunnable(Self, (Thread *) _owner)) {    return 0;  }  //如果当前_succ变量为空设置为Self,下次加速当前线程获得锁  if (_succ == NULL) {    _succ = Self;  }  Thread * prv = NULL;   while (--ctr >= 0) {    if ((ctr & 0xFF) == 0) {//如果ctr的低8位为0,判断是否需要阻塞      if (SafepointMechanism::should_block(Self)) {//线程安全点机制判断是否需要阻塞        goto Abort;           // abrupt spin egress      }      SpinPause();    }    Thread * ox = (Thread *) _owner;//获取锁对象拥有线程    if (ox == NULL) {//如果为空表示无锁      ox = (Thread*)Atomic::cmpxchg(Self, &_owner, (void*)NULL);//cas替换_owner为Self      if (ox == NULL) {//表示cas成功也即获得锁        if (_succ == Self) {          _succ = NULL;        }        int x = _SpinDuration;        if (x < Knob_SpinLimit) {          if (x < Knob_Poverty) x = Knob_Poverty;          _SpinDuration = x + Knob_Bonus;        }        return 1;//返回1      }      prv = ox;      goto Abort;    }    //后续皆为简单的条件判断,不做过多赘述    if (ox != prv && prv != NULL) {      goto Abort;    }    prv = ox;    if (NotRunnable(Self, ox)) {      goto Abort;    }    if (_succ == NULL) {      _succ = Self;    }  }  {    int x = _SpinDuration;    if (x > 0) {      x -= Knob_Penalty;      if (x < 0) x = 0;      _SpinDuration = x;    }  } Abort:  if (_succ == Self) {//如果_succ为当前self    _succ = NULL;//置为空    OrderAccess::fence();//全屏障保证后续可以看到最小值    if (TryLock(Self) > 0) return 1;//尝试获取锁,成功返回1  }  return 0;//返回0}
bytecodeInterpreter.cpp中的_monitorexit
CASE(_monitorexit): {        oop lockee = STACK_OBJECT(-1);//获取操作数栈上的锁对象        BasicObjectLock* limit = istate->monitor_base();        BasicObjectLock* most_recent = (BasicObjectLock*) istate->stack_base();        while (most_recent != limit ) {//遍历操作数栈上的对象找到要释放的锁对象          if ((most_recent)->obj() == lockee) {//如果当前对象等于lockee锁对象            BasicLock* lock = most_recent->lock();            markOop header = lock->displaced_header();// 获取被替换后的对象头部(偏向锁不替换,这里了解即可,轻量级锁时还会回来)            most_recent->set_obj(NULL);//将锁对象的持有者obj置为空            if (!lockee->mark()->has_bias_pattern()) {//判断是否有偏向锁              bool call_vm = UseHeavyMonitors;              if (header != NULL || call_vm) {                markOop old_header = markOopDesc::encode(lock);                if (call_vm || lockee->cas_set_mark(header, old_header) != old_header) {//cas设置mark头部为header                  // restore object for the slow case                  most_recent->set_obj(lockee);//还原锁对象                  CALL_VM(InterpreterRuntime::monitorexit(THREAD, most_recent), handle_exception);//进入monitorexit进一步释放锁                }              }            }            UPDATE_PC_AND_TOS_AND_CONTINUE(1, -1);          }          most_recent++;        }        // 非正常情况,抛出对应处理异常        CALL_VM(InterpreterRuntime::throw_illegal_monitor_state_exception(THREAD), handle_exception);        ShouldNotReachHere();      }
InterpreterRuntime::monitorexit
IRT_ENTRY_NO_ASYNC(void, InterpreterRuntime::monitorexit(JavaThread* thread, BasicObjectLock* elem))  Handle h_obj(thread, elem->obj());//获取锁对象    if (elem == NULL || h_obj()->is_unlocked()) {//如果锁对象为空或者没有锁    THROW(vmSymbols::java_lang_IllegalMonitorStateException());//抛出异常  }  ObjectSynchronizer::slow_exit(h_obj(), elem->lock(), thread);//进入slow_exit,慢退出,进一步解锁  // 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);//释放锁IRT_END    void ObjectSynchronizer::slow_exit(oop object, BasicLock* lock, TRAPS) {  fast_exit(object, lock, THREAD);}
fast_exit方法
void ObjectSynchronizer::fast_exit(oop object, BasicLock* lock, TRAPS) {  markOop mark = object->mark();//获取对象头部信息  markOop dhw = lock->displaced_header();//获取锁对象的头部  if (dhw == NULL) {//如果锁对象头部为空#ifndef PRODUCT    if (mark != markOopDesc::INFLATING()) {//如果对象不是膨胀中      // Only do diagnostics if we are not racing an inflation. Simply      // exiting a recursive enter of a Java Monitor that is being      // inflated is safe; see the has_monitor() comment below.      if (mark->has_monitor()) {//判断是否有重量级锁对象        // The BasicLock"s displaced_header is marked as a recursive        // enter and we have an inflated Java Monitor (ObjectMonitor).        // This is a special case where the Java Monitor was inflated        // after this thread entered the stack-lock recursively. When a        // Java Monitor is inflated, we cannot safely walk the Java        // Monitor owner"s stack and update the BasicLocks because a        // Java Monitor can be asynchronously inflated by a thread that        // does not own the Java Monitor.        ObjectMonitor * m = mark->monitor();//获取锁对象      }    }#endif    return;//返回  }  if (mark == (markOop) lock) {//如果头部mark等于当前锁对象    if (object->cas_set_mark(dhw, mark) == mark) {//cas替换mark头部为dhw      return;//直接返回    }  }  //锁膨胀后,进入exit方法  ObjectSynchronizer::inflate(THREAD,                              object,                              inflate_cause_vm_internal)->exit(true, THREAD);}
ObjectMonitor::exit
void ObjectMonitor::exit(bool not_suspended, TRAPS) {  Thread * const Self = THREAD;//获取当前的线程对象  if (THREAD != _owner) {//如果当前线程不等于锁对象的拥有者_owner线程    if (THREAD->is_lock_owned((address) _owner)) {//如果当前线程栈上的锁拥有者是当前_owner。此种情况可能是当业务持有轻量级锁在执行业务时,遇到了锁膨胀的过程,锁升级成重量级锁了      _owner = THREAD;      _recursions = 0;    } else {      return;//直接返回    }  }  if (_recursions != 0) {//锁重入,将当前重入次数减去1    _recursions--;        // this is simple recursive enter    return;  }  _Responsible = NULL;  for (;;) {    OrderAccess::release_store(&_owner, (void*)NULL);   // 释放锁,这里释放后,其他线程就可以尝试抢锁    OrderAccess::storeload(); //全屏障保证后续看到的值都是最新的    if ((intptr_t(_EntryList)|intptr_t(_cxq)) == 0 || _succ != NULL) {//如果_EntryList和_cxq为空直接返回,_succ表示有等待线程,也直接返回      return;    }    if (!Atomic::replace_if_null(THREAD, &_owner)) {//如果当前_owner为空替换为当前线程      return;//替换失败直接返回    }    ObjectWaiter * w = NULL;    w = _EntryList;//获取_EntryList    if (w != NULL) {//当前有线程需要继续执行      ExitEpilog(Self, w);//唤醒继续执行,直接返回      return;    }    w = _cxq;//获取竞争队列    if (w == NULL) continue;//队列为空,继续循环    for (;;) {//for循环将_cxq队列的值取出来并将_cxq队列置为空,      ObjectWaiter * u = Atomic::cmpxchg((ObjectWaiter*)NULL, &_cxq, w);//将_cxq队列置为空。      if (u == w) break;      w = u;    }    _EntryList = w;//将cxq队列赋值给_EntryList    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;//_succ不为空,表示有线程唤醒待执行    w = _EntryList;//获取_EntryList的任务    if (w != NULL) {//不为空,唤醒后续线程继续执行      guarantee(w->TState == ObjectWaiter::TS_ENTER, "invariant");      ExitEpilog(Self, w);      return;    }  }}
ObjectMonitor::ExitEpilog
void ObjectMonitor::ExitEpilog(Thread * Self, ObjectWaiter * Wakee) {  // Exit protocol:  // 1. ST _succ = wakee  // 2. membar #loadstore|#storestore;  // 2. ST _owner = NULL  // 3. unpark(wakee)  _succ = Wakee->_thread;//_succ置为要唤醒的线程  ParkEvent * Trigger = Wakee->_event;//获取线程阻塞的事件对象  // Hygiene -- once we"ve set _owner = NULL we can"t safely dereference Wakee again.  // The thread associated with Wakee may have grabbed the lock and "Wakee" may be  // out-of-scope (non-extant).  Wakee  = NULL;//置空  // Drop the lock 发布订阅,同时加上全屏障,保证后续可以看到变量的最新值  OrderAccess::release_store(&_owner, (void*)NULL);  OrderAccess::fence();                                DTRACE_MONITOR_PROBE(contended__exit, this, object(), Self);  Trigger->unpark();//唤醒线程  // Maintain stats and report events to JVMTI  OM_PERFDATA_OP(Parks, inc());}
4.留言

这些只是个人整理的知识点,中间可能有不到位的地方,烦请各位大佬指出

标签:

相关阅读

大家爱看

Kolas是“祭品”!郭正亮惊爆她不伦恋内幕 Kolas是“祭品”!郭正亮惊爆她不伦恋内幕

​蔡英文办公室发言人谷辣斯(KolasYotaka)今(28)日被《镜周刊》踢

最近更新