<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                [TOC] ## 三種使用方式 * 修飾普通的實例方法,對于普通的同步方法,鎖式當前實例對象 * 修飾靜態方法,對于靜態同步方法,鎖式當前類的Class對象 * 修飾代碼塊,對于同步方法塊,鎖是Synchronized配置的對象 ## java對象頭 ![](https://img.kancloud.cn/1a/a2/1aa25b32794bb76453c004bf46407f99_892x562.png) ”Mark Word"存儲一下消息 ~~~ hash:保存對象的哈希碼 age:GC分代年齡 biased_lock:偏向鎖標志 lock:鎖狀態標志 JavaThread* 當前線程 epoch:保存偏向時間戳 //其中關于當前鎖的狀態標志markOopDesc類中也進行了詳細的說明,具體代碼如下: enum { locked_value = 0,//輕量級鎖 對應[00] unlocked_value = 1,//無鎖狀態 對應[01] monitor_value = 2,//重量級鎖 對應[10] marked_value = 3,//GC標記 對應[11] biased_lock_pattern = 5//是否是偏向鎖 對應[101] 其中biased_lock一個bit位,lock兩個bit位 }; ~~~ ## synchronized鎖優化 Java SE 1.6為了減少獲得鎖和釋放鎖帶來的性能消耗,引入了“偏向鎖”和“輕量級鎖”。在Java SE 1.6中,鎖一共有4種狀態,級別從低到高依次是: 1. 無鎖狀態 2. 偏向鎖狀態 3. 輕量級鎖狀態 4. 重量級鎖狀態 這幾個狀態會隨著競爭情況逐漸升級,鎖**可以升級但不能降級**,意味著偏向鎖升級成輕量級鎖后不能降級成偏向鎖。這種鎖升級卻不能降級的策略,目的是為了提高獲得鎖和釋放鎖的效率 所謂的鎖,本質上就是一個共享變量,這個變量標識了某個共享對象是否被其他線程占用。 線程在訪問共享對象時,要先判斷該共享變量。 ### 偏向鎖 理解鎖被同一線程 在大多數情況下,鎖不僅不存在多線程競爭,而且總是由同一線程多次獲得。為了讓線程獲得鎖的代價更低而引入了偏向鎖 當一個線程訪問同步塊并獲取鎖時,會在對象頭中的“Mark word"和棧幀中的鎖記錄里存儲鎖偏向的線程ID。以后該線程在進入和退出同步塊時,不需要進行CAS操作來加鎖和解鎖。只需簡單地測試一下對象頭的”Mark Word“里是否存儲著指向當前線程的偏向鎖。如果測試成功,表示線程已經獲得了鎖。如果測試失敗,則需要再測試一下“Mark Word”中偏向鎖的標識是否設置成1(表示當前是偏向鎖):如果沒有設置,則使用CAS競爭鎖;如果設置了,則嘗試使用CAS將對象頭的偏向鎖指向當前線程。 ### 輕量級鎖 理解鎖被多個線程,但線程之間不存在競爭 * 線程在執行同步塊之前,JVM會先在當前線程的棧楨中創建用于存儲鎖記錄的空間,并將對象頭中的Mark Word復制到鎖記錄中,官方稱為Displaced Mark Word。 * 然后線程嘗試使用CAS將對象頭中的Mark Word替換為指向鎖記錄的指針。如果成功,當前線程獲得鎖,如果失敗,表示其他線程競爭鎖,當前線程便嘗試使用自旋來獲取鎖。 ### 重量級鎖 理解鎖被多個線程,且線程之間存在競爭 重量級鎖的競爭是在objectMonitor.cpp中ObjectMonitor::enter()方法中實現的。 簡述整個過程,可以是根據虛擬機規范的要求,在執行monitorenter指令時: 1. 首先要嘗試獲取對象的鎖。 2. 如果這個對象沒被鎖定,或者當前線程已經擁有了那個對象的鎖,把鎖的計數器加1。相應的,在執行monitorexit指令時會將鎖計數器減1,當計數器為0時,鎖就被釋放。 3. 如果獲取對象鎖失敗,那當前線程就要阻塞等待,直到對象鎖被另外一個線程釋放為止。 虛擬機規范對monitorenter和monitorexit的行為描述中,有兩點是需要特別注意的。 1. synchronized同步塊對同一條線程來說是可重入的,不會出現自己把自己鎖死的問題 2. 同步塊在已進入的線程執行完之前,會阻塞后面其他線程的進入。 **ObjectMonitor結構** 在講解具體的鎖獲取之前,我們需要了解**每個鎖對象(這里指已經升級為重量級鎖的對象)都有一個ObjectMonitor(對象監視器)**。也就是說**每個線程獲取鎖對象都會通過ObjectMonitor** ~~~ class ObjectMonitor { public: enum { OM_OK, // 沒有錯誤 OM_SYSTEM_ERROR, // 系統錯誤 OM_ILLEGAL_MONITOR_STATE, // 監視器狀態異常 OM_INTERRUPTED, // 當前線程已經中斷 OM_TIMED_OUT // 線程等待超時 }; volatile markOop _header; // 線程幀棧中存儲的 鎖對象的mark word拷貝 protected: // protected for JvmtiRawMonitor void * volatile _owner; // 指向獲得objectMonitor的線程或者 BasicLock對象 volatile jlong _previous_owner_tid; // 上一個獲得objectMonitor的線程id volatile intptr_t _recursions; // 同一線程重入鎖的次數,如果是0,表示第一次進入 ObjectWaiter * volatile _EntryList; // 在進入或者重進入阻塞狀態下的線程鏈表 protected: ObjectWaiter * volatile _WaitSet; // 處于等待狀態下的線程鏈表 ObjectWaiter volatile jint _waiters; //處于等待狀態下的線程個數 } ~~~ 重量級級鎖的競爭步驟,主要分為以下幾個步驟: 1. 通過CAS操作嘗試吧monitor的\_owner( 指向獲得objectMonitor的線程或者 BasicLock對象)設置為當前線程,如果CAS操作成功,表示線程獲取鎖成功,直接執行同步代碼塊。 2. 如果是同一線程重入鎖,則記錄當前重入的次數。 3. 如果2,3步驟都不滿足,則開始競爭鎖,走EnterI()方法。 EnterI()方法實現如下: 1. 把當前線程被封裝成ObjectWaiter的node對象,同時將該線程狀態設置為TS\_CXQ(競爭狀態) 2. 在for循環中,通過CAS把node節點push到\_cxq鏈表中,如果CAS操作失敗,繼續嘗試,是因為當期\_cxq鏈表已經發生改變了繼續for循環,如果成功直接返回。 3. 將node節點push到\_cxq鏈表之后,通過自旋嘗試獲取鎖(TryLock方法獲取鎖),如果循環一定次數后,還獲取不到鎖,則通過park函數掛起。(并不會消耗CPU資源) 重量級鎖的釋放可以分為以下步驟: 1. 判斷當前鎖對象中的\_owner沒有指向當前線程,如果\_owner指向的BasicLock在當前線程棧上,那么將\_owner指向當前線程。 2. 如果當前鎖對象中的\_owner指向當前線程,則判斷當前線程重入鎖的次數,如果不為0,那么就重新走ObjectMonitor::exit(),直到重入鎖次數為0為止。 3. 釋放當前鎖,并根據QMode的模式判斷,是否將\_cxq中掛起的線程喚醒。還是其他操作。 ## 參考資料 [Java并發編程:synchronized](https://blog.csdn.net/fei20121106/article/details/83268379)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看