<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>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                [TOC] ## **Synchronized**同步鎖 synchronized?它可以把任意一個非?NULL?的對象當作鎖。他屬于獨占式的悲觀鎖,同時屬于可重 入鎖。 ### **Synchronized作用范圍** 1. 作用于方法時,鎖住的是對象的實例(this); 2. 當作用于靜態方法時,鎖住的是?Class?實例,又因為?Class?的相關數據存儲在永久帶?PermGen (jdk1.8?則是?metaspace?),永久帶是全局共享的,因此靜態方法鎖相當于類的一個全局鎖, 會鎖所有調用該方法的線程; 3. synchronized?作用于一個對象實例時,鎖住的是所有以該對象為鎖的代碼塊。它有多個隊列, 當多個線程一起訪問某個對象監視器的時候,對象監視器會將這些線程存儲在不同的容器中。 ### **Synchronized核心組件** 1)**WaitSet**:哪些調用wait方法被阻塞的線程被放置在這里; 2)**Contention?List**:競爭隊列,所有請求鎖的線程首先被放在這個競爭隊列中; 3)**Entry?List**:Contention?List?中那些有資格成為候選資源的線程被移動到?Entry?List?中; 4)**OnDeck**?:任意時刻,最多只有一個線程正在競爭鎖資源,該線程被成為?OnDeck; 5)**Owner**:當前已經獲取到所資源的線程被稱為Owner; 6)**!Owner**:當前釋放鎖的線程。 ### **Synchronized實現** :-: ![](https://box.kancloud.cn/d8a98f76177f4347faca253d8a61da1f_570x252.jpg) 1. JVM?每次從隊列的尾部取出一個數據用于鎖競爭候選者(?OnDeck?),但是并發情況下,ContentionList?會被大量的并發線程進行?CAS?訪問,為了降低對尾部元素的競爭,JVM?會將一部分線程移動到?EntryList?中作為候選競爭線程。 <br> 2. Owner?線程會在?unlock?時,將?ContentionList?中的部分線程遷移到?EntryList?中,并指定EntryList?中的某個線程為?OnDeck?線程(一般是最先進去的那個線程)。 <br> 3. Owner?線程并不直接把鎖傳遞給?OnDeck?線程,而是把鎖競爭的權利交給?OnDeck?,OnDeck?需要重新競爭鎖。這樣雖然犧牲了一些公平性,但是能極大的提升系統的吞吐量,在JVM?中,也把這種選擇行為稱之為“競爭切換”。 <br> 4. OnDeck?線程獲取到鎖資源后會變為?Owner?線程,而沒有得到鎖資源的仍然停留在?EntryList中。如果?Owner?線程被?wait?方法阻塞,則轉移到?WaitSet?隊列中,直到某個時刻通過?notify或者?notifyAll?喚醒,會重新進去?EntryList?中。 <br> 5. 處于?ContentionList?、?EntryList?、WaitSet?中的線程都處于阻塞狀態,該阻塞是由操作系統來完成的(Linux?內核下采用?pthread\_mutex\_lock?內核函數實現的)。 <br> 6. Synchronized?是**非公平鎖**。?Synchronized?在線程進入?ContentionList?時,等待的線程會先嘗試自旋獲取鎖,如果獲取不到就進入?ContentionList,這明顯對于已經進入隊列的線程是不公平的,還有一個不公平的事情就是自旋獲取鎖的線程還可能直接搶占?OnDeck?線程的鎖資源。 參考:[https://blog.csdn.net/zqz\_zqz/article/details/70233767](http://https:/blog.csdn.net/zqz_zqz/article/details/70233767) <br> 7. 每個對象都有個?monitor?對象,加鎖就是在競爭?monitor?對象,代碼塊加鎖是在前后分別加上?monitorenter?和?monitorexit?指令來實現的,方法加鎖是通過一個標記位來判斷的 <br> 8. synchronized是一個**重量級**操作,需要調用操作系統相關接口,性能是低效的,有可能給線程加鎖消耗的時間比有用操作消耗的時間更多。 <br> 9. Java1.6?,synchronized?進行了很多的優化,有適應自旋、鎖消除、鎖粗化、輕量級鎖及偏向鎖等,效率有了本質上的提高。在之后推出的?Java1.7?與?1.8?中,均對該關鍵字的實現機理做了優化。引入了偏向鎖和輕量級鎖。都是在對象頭中有標記位,不需要經過操作系統加鎖。 <br> 10.鎖可以從偏向鎖升級到輕量級鎖,再升級到重量級鎖。這種升級過程叫做鎖膨脹; <br> 11.JDK?1.6?中默認是開啟偏向鎖和輕量級鎖,可以通過?-XX:-UseBiasedLocking?來禁用偏向鎖。 <br> ### **synchronized用法** **1\. 同步一個代碼塊** ~~~java public void func() { synchronized (this) { // ... } } ~~~ 它只作用于同一個對象,如果調用兩個對象上的同步代碼塊,就不會進行同步。 對于以下代碼,使用 ExecutorService 執行了兩個線程,由于調用的是同一個對象的同步代碼塊,因此這兩個線程會進行同步,當一個線程進入同步語句塊時,另一個線程就必須等待。 ~~~java public class SynchronizedExample { public void func1() { synchronized (this) { for (int i = 0; i < 10; i++) { System.out.print(i + " "); } } } } ~~~ ~~~java public static void main(String[] args) { SynchronizedExample e1 = new SynchronizedExample(); ExecutorService executorService = Executors.newCachedThreadPool(); executorService.execute(() -> e1.func1()); executorService.execute(() -> e1.func1()); } ~~~ ~~~java 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 ~~~ 對于以下代碼,兩個線程調用了不同對象的同步代碼塊,因此這兩個線程就不需要同步。從輸出結果可以看出,兩個線程交叉執行。 ~~~java public static void main(String[] args) { SynchronizedExample e1 = new SynchronizedExample(); SynchronizedExample e2 = new SynchronizedExample(); ExecutorService executorService = Executors.newCachedThreadPool(); executorService.execute(() -> e1.func1()); executorService.execute(() -> e2.func1()); } ~~~ ~~~ 0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 ~~~ **2\. 同步一個方法** ~~~java public synchronized void func () { // ... } ~~~ 它和同步代碼塊一樣,作用于同一個對象。 **3\. 同步一個類** ~~~java public void func() { synchronized (SynchronizedExample.class) { // ... } } ~~~ 作用于整個類,也就是說兩個線程調用同一個類的不同對象上的這種同步語句,也會進行同步。 ~~~java public class SynchronizedExample { public void func2() { synchronized (SynchronizedExample.class) { for (int i = 0; i < 10; i++) { System.out.print(i + " "); } } } } ~~~ ~~~java public static void main(String[] args) { SynchronizedExample e1 = new SynchronizedExample(); SynchronizedExample e2 = new SynchronizedExample(); ExecutorService executorService = Executors.newCachedThreadPool(); executorService.execute(() -> e1.func2()); executorService.execute(() -> e2.func2()); } ~~~ ~~~ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 ~~~ **4\. 同步一個靜態方法** * 非靜態同步函數的鎖是:this * 靜態的同步函數的鎖是:字節碼對象 ~~~java public synchronized static void fun() { // ... } ~~~ 作用于整個類。
                  <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>

                              哎呀哎呀视频在线观看