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

                # CPUCacheTest 更多的討論 CPUCacheTest 經常作為大廠的面試題,難倒很多精通多線程并發的面試者,這里列出這個題目盡可能多的答案。綜合考慮了變量可見性,線程上下文切換,以及JIT優化。 如下一段程序,期望當主線程A設置stop變量為true的時候,線程B退出循環。 但實際上線程B看不到更新后的值,從而一直循環下去。 ~~~java public class CPUCacheTest { private static boolean stop = false; public static void main(String[] args){ Thread a = new Thread("B"){ public void run(){ while (!stop) { int a = 1; } System.out.println("exit"); } }; a.start(); pause(100); //停止標記,但未能停止線程B stop = true; } public static void pause(int time){ try { TimeUnit.MILLISECONDS.sleep(time); }catch(Exception ex){ } } } ~~~ ## 原因分析 在第三章已經說過,多線程下變量的可見性,需要添加`volatile` 關鍵字,保證stop變量能被其他線程看到 ```java private static volatile boolean stop = false; ``` ## 場景一 判斷如下代碼是否也能保證線程B退出 ```java Thread a = new Thread("B"){ public void run(){ while (!stop) { System.out.println("in loop"); } System.out.println("exit"); } }; ``` 答案,能退出,因為方法`out.println()`實際上如下實現,synchronized保證變量可見性 ```java private void write(String s) { synchronized (this) { ..... } } ``` ## 場景二 判斷如下代碼是否也能保證線程B退出,調用pause方法,休眠1毫秒 ```java Thread a = new Thread("B"){ public void run(){ while (!stop) { pause(1); } System.out.println("exit"); } }; ``` 答案,能退出,pause方法引起線程休眠,再次喚醒的時候,上下文切換,線程B能得到stop最新的變量 ## 場景三 判斷如下代碼是否也能保證線程B退出,定義int類型的變量b,在循環里自增 ``` public class CPUCacheTest { private static /* volatile */ boolean stop = false; static int b = 1; public static void main(String[] args){ Thread a = new Thread("B"){ public void run(){ while (!stop) { b++ } System.out.println("exit "+b); } }; System.out.println("start"); a.start(); pause(100); stop = true; } ``` 答案,不能退出,沒有任何原因觸發變量可見性 ## 場景四 判斷如下代碼是否也能保證線程B退出,定義Integer類型的變量b,在循環里自增 ```java public class CPUCacheTest { private static /* volatile */ boolean stop = false; static Integer b = 1; public static void main(String[] args){ Thread a = new Thread("B"){ public void run(){ while (!stop) { b++ } System.out.println("exit "+b); } }; System.out.println("start"); a.start(); pause(100); stop = true; } ``` 答案,能退出,因為如上代碼`b++` 實際的操作如下。 ```java int temp = b.intValue(); temp++; b = new Integer(temp); ``` 因為Integer定義如下,因為變量是final,保證了變量可見性 ```java private final int value; public Integer(int value) { this.value = value; } ``` ## 場景五 判斷如下代碼是否也能保證線程B退出,while循環里定義Integer 變量,并自增 ```java public class CPUCacheTest { private static /* volatile */ boolean stop = false; public static void main(String[] args){ Thread a = new Thread("B"){ public void run(){ while (!stop) { Integer c = 1; c++; } System.out.println("exit "+b); } }; System.out.println("start"); a.start(); pause(100); stop = true; } ``` 答案,不能退出,在while循環里,變量c的操作被JIT優化成如下代碼 ```java Thread a = new Thread("B"){ public void run(){ while (!stop) { //代碼被消除 } System.out.println("exit "+b); } }; ``` ## 場景六 判斷如下代碼是否也能保證線程B退出,while循環里定義Integer 變量c,自增后賦值給b ```java public class CPUCacheTest { private static /* volatile */ boolean stop = false; static int b = 1; public static void main(String[] args){ Thread a = new Thread("B"){ public void run(){ while (!stop) { Integer c = 1; c++; b=c; } System.out.println("exit "+b); } }; System.out.println("start"); a.start(); pause(100); stop = true; } ``` 答案,不能退出,變量c 賦值到b操作會提取到循環外執行,這涉及到JIT編譯器優化,表達式提升(hoisting),運行代碼如下 ```java Thread a = new Thread("B"){ public void run(){ Integer c = 1; c++; b=c; while (!stop) { } System.out.println("exit "+b); } }; ``` ## 場景七 判斷如下代碼是否也能保證線程B退出,while循環里使用StringBuffer ```java Thread a = new Thread("B"){ public void run(){ while (!stop) { StringBuffer sb = new StringBuffer(); sb.append("abc"); } System.out.println("exit "+b); } }; ``` 答案,能退出,StringBuffer 的append方法有關鍵字synchronzied ```java @Override public synchronized StringBuffer append(String str) { toStringCache = null; super.append(str); return this; } ``` ## 場景八 同場景3,但運行這個程序加上虛擬機參數 -Xint ,程序能正確退出么? ```java public class CPUCacheTest { private static /* volatile */ boolean stop = false; static int b = 1; public static void main(String[] args){ Thread a = new Thread("B"){ public void run(){ while (!stop) { b++ } System.out.println("exit "+b); } }; System.out.println("start"); a.start(); pause(100); stop = true; } ``` 在第8章JIT說過,-Xint 是讓Java解釋執行,這樣,不會涉及到變量可見性,因此無論while循環里是什么,都能退出
                  <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>

                              哎呀哎呀视频在线观看