第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

為什么i ++不是原子的?

為什么i ++不是原子的?

瀟湘沐 2019-08-19 10:38:39
為什么i ++不是原子的?為什么i++Java中沒有原子?為了更深入地了解Java,我試圖計算線程循環(huán)執(zhí)行的頻率。所以我用了一個private static int total = 0;在主要班級。我有兩個主題。線程1:打印 System.out.println("Hello from Thread 1!");線程2:打印 System.out.println("Hello from Thread 2!");并且我計算由線程1和線程2打印的線。但是線程1的線+線程2的線與打印出的總線數(shù)不匹配。這是我的代碼:import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.logging.Level;import java.util.logging.Logger;public class Test {     private static int total = 0;     private static int countT1 = 0;     private static int countT2 = 0;     private boolean run = true;     public Test() {         ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();         newCachedThreadPool.execute(t1);         newCachedThreadPool.execute(t2);         try {             Thread.sleep(1000);         }         catch (InterruptedException ex) {             Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);         }         run = false;         try {             Thread.sleep(1000);         }         catch (InterruptedException ex) {             Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);         }         System.out.println((countT1 + countT2 + " == " + total));     }     private Runnable t1 = new Runnable() {         @Override         public void run() {             while (run) {                 total++;                 countT1++;                 System.out.println("Hello #" + countT1 + " from Thread 2! Total hello: " + total);             }         }     };     private Runnable t2 = new Runnable() {         @Override         public void run() {             while (run) {                 total++;                 countT2++;                 System.out.println("Hello #" + countT2 + " from Thread 2! Total hello: " + total);             }         }     };     public static void main(String[] args) {         new Test();     }}
查看完整描述

3 回答

?
縹緲止盈

TA貢獻2041條經(jīng)驗 獲得超4個贊

i++在Java中可能不是原子的,因為原子性是一個特殊的要求,在大多數(shù)用途中都不存在i++。該要求具有顯著的開銷:使增量操作成為原子的成本很高; 它涉及在普通增量中不需要存在的軟件和硬件級別的同步。

您可以將i++應(yīng)該設(shè)計和記錄的參數(shù)設(shè)置為專門執(zhí)行原子增量,以便使用執(zhí)行非原子增量i = i + 1。但是,這會破壞Java,C和C ++之間的“文化兼容性”。同樣,它會刪除一個方便的符號,熟悉類C語言的程序員認(rèn)為這是理所當(dāng)然的,賦予它一個特殊的含義,僅適用于有限的情況。

基本的C或C ++代碼就像for (i = 0; i < LIMIT; i++)轉(zhuǎn)換為Java一樣for (i = 0; i < LIMIT; i = i + 1); 因為使用原子是不合適的i++。更糟糕的是,程序員從C語言或其他類C語言到Java都會使用i++,導(dǎo)致不必要地使用原子指令。

即使在機器指令集級別,由于性能原因,增量類型操作通常也不是原子的。在x86中,必須使用特殊指令“l(fā)ock prefix”來使inc指令成為原子:出于與上述相同的原因。如果inc總是原子的,那么當(dāng)需要非原子公司時,它永遠不會被使用; 程序員和編譯器會生成加載,添加1和存儲的代碼,因為它會更快。

在一些指令集架構(gòu)中,沒有原子inc或根本沒有inc; 要在MIPS上執(zhí)行原子公司,你必須編寫一個使用lland sc:load-linked和store-conditional 的軟件循環(huán)。加載鏈接讀取單詞,如果單詞未更改,則store-conditional存儲新值,否則失?。z測到并導(dǎo)致重新嘗試)。


查看完整回答
反對 回復(fù) 2019-08-19
?
四季花海

TA貢獻1811條經(jīng)驗 獲得超5個贊

i++ 涉及兩個操作:


讀取當(dāng)前值 i

遞增值并將其分配給 i

當(dāng)兩個線程i++同時對同一個變量執(zhí)行時,它們可能都獲得相同的當(dāng)前值i,然后遞增并設(shè)置為i+1,因此您將獲得單個增量而不是兩個。


示例:


int i = 5;

Thread 1 : i++;

           // reads value 5

Thread 2 : i++;

           // reads value 5

Thread 1 : // increments i to 6

Thread 2 : // increments i to 6

           // i == 6 instead of 7


查看完整回答
反對 回復(fù) 2019-08-19
?
守著星空守著你

TA貢獻1799條經(jīng)驗 獲得超8個贊

為什么i ++在Java中不是原子的?

讓我們將增量操作分解為多個語句:

線程1和2:

  1. 從內(nèi)存中獲取總值

  2. 將1添加到值

  3. 寫回內(nèi)存

如果沒有同步,那么讓我們說線程1讀取值3并將其增加到4,但是沒有寫回來。此時,發(fā)生上下文切換。線程2讀取值3,遞增它并發(fā)生上下文切換。雖然兩個線程都增加了總值,但仍然是4 - 競爭條件


查看完整回答
反對 回復(fù) 2019-08-19
  • 3 回答
  • 0 關(guān)注
  • 707 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學(xué)習(xí)伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號