面試刷題15:synchronized底層是如何實現的?

image.png


全部的同步場景都是基於鎖。鎖在併發編程中發揮重要做用。


我是李福春,我在準備面試,今天的題目是:




java

synchronized底層是如何實現的?c++

答: synchronized是在底層的jvm中實現的,即c++寫的,synchronized的實現是基於一對monitorenter, monitorexit指令實現的,monitor對象是同步的基本實現單元。


在java6中,monitor依靠操做系統提供的內部互斥鎖,須要在用戶態空間和內核態空間切換,因此同步操做是一個比較重的操做,開銷比較大。


在java7以後,monitor有三種不一樣的實現,即偏斜鎖,輕量級鎖,重量級鎖。


基於對象頭的markword,標記上偏向的線程id, 在沒有競爭的條件下,使用的是偏斜鎖;
當有多個線程來競爭偏斜鎖,基於cas對對象頭的markword來進行競爭,若是拿到了,升級爲輕量級鎖。
沒拿到則升級爲重量級鎖;


鎖降級發生在jvm進入安全點檢查的時候,對monitor進行降級。


面試

synchronized底層實現


對象頭結構:
編程

image.png






sharedRuntime.cpp 解釋器和編譯器的運行時基類。安全

Handle h_obj(THREAD, obj);
  if (UseBiasedLocking) {
    // Retry fast entry if bias is revoked to avoid unnecessary inflation
    ObjectSynchronizer::fast_enter(h_obj, lock, true, CHECK);
  } else {
    ObjectSynchronizer::slow_enter(h_obj, lock, CHECK);
  }




偏斜鎖邏輯代碼:
併發

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




輕量級鎖:jvm

void ObjectSynchronizer::slow_enter(Handle obj, BasicLock* lock, TRAPS) {
  markOop mark = obj->mark();
 if (mark->is_neutral()) {
       // 將目前的Mark Word複製到Displaced Header上
  lock->set_displaced_header(mark);
  // 利用CAS設置對象的Mark Word
    if (mark == obj()->cas_set_mark((markOop) lock, mark)) {
      TEVENT(slow_enter: release stacklock);
      return;
    }
    // 檢查存在競爭
  } else if (mark->has_locker() &&
             THREAD->is_lock_owned((address)mark->locker())) {
  // 清除
    lock->set_displaced_header(NULL);
    return;
  }
 
  // 重置Displaced Header
  lock->set_displaced_header(markOopDesc::unused_mark());
  ObjectSynchronizer::inflate(THREAD,
                            obj(),
                              inflate_cause_monitor_enter)->enter(THREAD);
}






java體系中的鎖






java提供的鎖有哪些


優化

image.png








再入讀寫鎖:


spa

public class RWSample {
  private final Map<String, String> m = new TreeMap<>();
  private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
  private final Lock r = rwl.readLock();
  private final Lock w = rwl.writeLock();
  public String get(String key) {
      r.lock();
      System.out.println("讀鎖鎖定!");
      try {
          return m.get(key);
      } finally {
          r.unlock();
      }
  }

  public String put(String key, String entry) {
      w.lock();
  System.out.println("寫鎖鎖定!");
        try {
            return m.put(key, entry);
        } finally {
            w.unlock();
        }
    }
  // …
  }


優化的讀寫鎖:StampedLock
代碼以下:
讀取以前先經過validate方法判斷是否進入寫狀態,若是沒有進入寫狀態,不用加讀鎖,避免了開銷;
不然增長讀鎖,保證一致性。
操作系統

public class StampedSample {
  private final StampedLock sl = new StampedLock();

  void mutate() {
      long stamp = sl.writeLock();
      try {
          write();
      } finally {
          sl.unlockWrite(stamp);
      }
  }

  Data access() {
      long stamp = sl.tryOptimisticRead();
      Data data = read();
      if (!sl.validate(stamp)) {
          stamp = sl.readLock();
          try {
              data = read();
          } finally {
              sl.unlockRead(stamp);
          }
      }
      return data;
  }
  // …
}


小結


本篇先介紹了synchronized的底層實現原理,介紹了java8中引入的3種級別的鎖,以及鎖升級和降級過程。


而後介紹了java體系中的其它的鎖和優化讀寫鎖使用場景。








image.png

原創不易,轉載請註明出處,讓咱們互通有無,共同進步,歡迎溝通交流。
相關文章
相關標籤/搜索