请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

线程第一次拿到偏向锁,仍然是通过CAS操作拿到的?

老师好,最后一分钟讲到偏向锁的优点,说加锁和解锁不需要执行CAS操作,我从其它地方了解的是说,比如第一次的时候A线程通过CAS操作拿到锁的,后面A线程重进入的时候,就不需要再次进行CAS操作了,这个时候确实是没有消耗的。想请教下到底是怎样的呢

正在回答 回答被采纳积分+3

1回答

翔仔 2020-05-24 00:43:23

同学好,第一次还是通过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;
      }


1 回复 有任何疑惑可以回复我~
  • 提问者 慕哥6062902 #1
    感谢老师!
    回复 有任何疑惑可以回复我~ 2020-05-24 01:41:31
  • 翔仔,在另一个问题中你说:“偏向锁没有CAS,只是在对象头存了下threadid”,但是这里看第一次获取偏向锁是有CAS操作的。
    回复 有任何疑惑可以回复我~ 2021-12-07 13:24:03
  • 翔仔 回复 Meteor流星 #3
    是的,前后有点矛盾了,以这个源码为准,不然理解上容易有偏差
    回复 有任何疑惑可以回复我~ 2021-12-07 23:58:37
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信