<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智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                _**Java虛擬機規范定義的許多規則中的一條:所有對基本類型的操作除了某些對long類型和double類型的操作之外,都是原子級的;**_ > 當線程把主存中的 long/double類型的值讀到線程內存中時,可能是兩次32位值的寫操作,顯而易見,如果幾個線程同時操作,那么就可能會出現高低2個32位值出錯的情況發生。即long,double高低位問題,非線程安全 舉例說明: 即如有一個long類型的field字段,某個線程正在執行 field = 123L ,而同時有另一個線程正在執行 field = 456L,這樣的指定操作之后field的值會是什么,是無法保證的。也許是123L,也可能是456L,或許是0L,甚至還可能是31415926L ### JVM內存模型中定義了8種原子操作 1. lock:將一個變量標識為被一個線程獨占狀態 2. unclock:將一個變量從獨占狀態釋放出來,釋放后的變量才可以被其他線程鎖定 3. read:將一個變量的值從主內存傳輸到工作內存中,以便隨后的load操作 4. load:把read操作從主內存中得到的變量值放入工作內存的變量的副本中 5. use:把工作內存中的一個變量的值傳給執行引擎,每當虛擬機遇到一個使用到變量的指令時都會使用該指令 6. assign:把一個從執行引擎接收到的值賦給工作內存中的變量,每當虛擬機遇到一個給變量賦值的指令時,都要使用該操作 7. store:把工作內存中的一個變量的值傳遞給主內存,以便隨后的write操作 8. write:把store操作從工作內存中得到的變量的值寫到主內存中的變量 對于32位操作系統來說單次次操作能處理的最長長度為32bit,而long類型8字節64bit,所以對long的讀寫都要兩條指令才能完成\(即每次讀寫64bit中的32bit\);如果JVM要保證long和double讀寫的原子性,勢必要做額外的處理 ``` public class LongAtomTest implements Runnable { private static long field = 0; private volatile long value; public long getValue() { return value; } public void setValue(long value) { this.value = value; } public LongAtomTest(long value) { this.setValue(value); } @Override public void run() { int i = 0; while (i < 100000) { LongAtomTest.field = this.getValue(); i++; long temp = LongAtomTest.field; if (temp != 1L && temp != -1L) { System.out.println("出現錯誤結果" + temp); System.exit(0); } } System.out.println("運行正確"); } public static void main(String[] args) throws InterruptedException { // 獲取并打印當前JVM是32位還是64位的 String arch = System.getProperty("sun.arch.data.model"); System.out.println(arch+"-bit"); LongAtomTest t1 = new LongAtomTest(1); LongAtomTest t2 = new LongAtomTest(-1); Thread T1 = new Thread(t1); Thread T2 = new Thread(t2); T1.start(); T2.start(); T1.join(); T2.join(); } } ``` 以上代碼在32位JVM上和64位JVM上運行結果將不一致 從程序得到的結果來看,32位的HotSpot沒有把long和double的讀寫實現為原子操作。 在讀寫的時候,分成兩次操作,每次讀寫32位。因為采用了這種策略,所以64位的long和double的讀與寫都不是原子操作 ### 結論 * 對于64位的long和double,如果沒有被volatile修飾,那么對其操作可以不是原子的。在操作的時候,可以分成兩步,每次對32位操作; * 如果使用volatile修飾long和double,那么其讀寫都是原子操作; * 在實現JVM時,可以自由選擇是否把讀寫long和double作為原子操作; * java中對于long和double類型的寫操作不是原子操作,而是分成了兩個32位的寫操作。讀操作是否也分成了兩個32位的讀呢?在JSR-133之前的規范中,讀也是分成了兩個32位的讀,但是從JSR-133規范開始,即JDK5開始,讀操作也都具有原子性; * java中對于其他類型的讀寫操作都是原子操作\(除long和double類型以外\); * 對于引用類型的讀寫操作都是原子操作,無論引用類型的實際類型是32位的值還是64位的值; * 對于long類型的不恰當操作可能讀取到從未出現過的值。而對于int的不恰當操作則可能讀取到舊的值;
                  <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>

                              哎呀哎呀视频在线观看