AtomicInteger類和int原生類型自增鮮明的對比


AtomicInteger這個類的存在是為了滿足在高並發的情況下,原生的整形數值自增線程不安全的問題。比如說

    int i = 0 ; i++;
  • 1
  • 2

上面的寫法是線程不安全的。
有的人可能會說了,可以使用synchronized關鍵字啊。
但是這里筆者要說的是,使用了synchronized去做同步的話系統的性能將會大大下降。
所以此時AtomicInteger這個類的使用就可以滿足上述的情況。
當我們統計一個頁面的瀏覽量的時候,可以使用該類來統計,而不再使用++運算符。

但是在使用的過程中,筆者發現,使用++運算符和AtomicInteger的結果都是對的。。。

結果有點暈了,難道結論是錯的么?當然不是了。
注意這個類使用的情況下是在高並發量的情況下。不是同時啟10個20個線程,而是成千上萬個線程。

我們先看看AtomicInteger類起作用的代碼

import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicInteger; public class AtomicIntegerTest { public static final AtomicInteger atomicInteger = new AtomicInteger(0); public static void main(String[] args) throws InterruptedException { atomicIntegerTest(); Thread.sleep(3000); System.out.println("最終結果是" + atomicInteger.get()); } private static void atomicIntegerTest() { ExecutorService executorService = Executors.newFixedThreadPool(10000); for (int i = 0; i < 10000; i++) { executorService.execute(() -> { for (int j = 0; j < 4; j++) { System.out.println(atomicInteger.getAndIncrement()); } }); } executorService.shutdown(); } } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

打印的結果是4萬
這里寫圖片描述
再看看++操作符

    import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class IntValueIncrementTest { public static int value = 0; public static void main(String[] args) throws InterruptedException { ExecutorService executorService = Executors.newFixedThreadPool(10000); for (int i = 0; i < 10000; i++) { executorService.execute(() -> { for (int j = 0; j < 4; j++) { System.out.println(value++); } }); } executorService.shutdown(); Thread.sleep(3000); System.out.println("最終結果是" + value); } } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

這里寫圖片描述
我們可以看到結果是39972,顯然結果丟失了一些。
所以在高並發的情況下應當使用AtomicInteger類

當我們在並發情況下,但是並發量又不是那么大的時候,
我們將上述的代碼改掉,改為同時只有10個線程在修改數值。
我們貼代碼

import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicInteger; public class AtomicIntegerTest { public static final AtomicInteger atomicInteger = new AtomicInteger(0); public static void main(String[] args) throws InterruptedException { atomicIntegerTest(); Thread.sleep(3000); System.out.println("最終結果是" + atomicInteger.get()); } private static void atomicIntegerTest() { ExecutorService executorService = Executors.newFixedThreadPool(10000); for (int i = 0; i < 10; i++) { executorService.execute(() -> { for (int j = 0; j < 4; j++) { System.out.println(atomicInteger.getAndIncrement()); } }); } executorService.shutdown(); } } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

這里寫圖片描述
運行的結果是40

再貼10個線程的並發量的情形。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class IntValueIncrementTest { public static int value = 0; public static void main(String[] args) throws InterruptedException { ExecutorService executorService = Executors.newFixedThreadPool(10000); for (int i = 0; i < 10; i++) { executorService.execute(() -> { for (int j = 0; j < 4; j++) { System.out.println(value++); } }); } executorService.shutdown(); Thread.sleep(3000); System.out.println("最終結果是" + value); } } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

這里寫圖片描述
發現此時的結果也是40。
所以這就給人一種假象:
1)AtomicInteger類不起作用.
2)i++或者++i是線程安全的
其實上面兩點觀念都是錯誤的。是因為並發量不夠高而已
但是需要注意的是AtomicInteger類只能保證在自增或者自減的情況下保證線程安全

轉自 https://blog.csdn.net/u013803262/article/details/72452932


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM