600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > java 原子性加法_Java多線程之原子性 volatile atomicInteger測試

java 原子性加法_Java多線程之原子性 volatile atomicInteger測試

时间:2021-06-10 01:26:09

相关推荐

java 原子性加法_Java多線程之原子性 volatile atomicInteger測試

一、補充概念

1.什么是線程安全性?

《Java Concurrency in Practice》中有提到:當多個線程訪問某個類時,這個類始終都能表現出正確的行為,那么就稱這個類是線程安全的。

2.Java中的“同步”

Java中的主要同步機制是關鍵字“synchronized”,它提供了一種獨占的加鎖方式,但“同步”這個術語還包括volatile類型的變量,顯式鎖(Explicit Lock)以及原子變量。

2.原子性

原子是世界上的最小單位,具有不可分割性。比如 a=0;(a非long和double類型)這個操作是不可分割的,那么我們說這個操作時原子操作。再比如:a++;這個操作實際是a = a + 1;是可分割的,所以他不是一個原子操作。非原子操作都會存在線程安全問題,需要我們使用同步技術(sychronized)來讓它變成一個原子操作。一個操作是原子操作,那么我們稱它具有原子性。java的concurrent包下提供了一些原子類,我們可以通過閱讀API來了解這些原子類的用法。比如:AtomicInteger、AtomicLong、AtomicReference等。

二、實例源碼

1 public class IncrementTestDemo {

2

3 public static int count = 0;

4 public static Counter counter = new Counter();

5 public static AtomicInteger atomicInteger = new AtomicInteger(0);

6 volatile public static int countVolatile = 0;

7

8 public static void main(String[] args) {

9 for (int i = 0; i < 10; i++) {

10 new Thread() {

11 public void run() {

12 for (int j = 0; j < 1000; j++) {

13 count++;

14 counter.increment();

15 atomicInteger.getAndIncrement();

16 countVolatile++;

17 }

18 }

19 }.start();

20 }

21 try {

22 Thread.sleep(3000);

23 } catch (InterruptedException e) {

24 e.printStackTrace();

25 }

26

27 System.out.println("static count: " + count);

28 System.out.println("Counter: " + counter.getValue());

29 System.out.println("AtomicInteger: " + atomicInteger.intValue());

30 System.out.println("countVolatile: " + countVolatile);

31 }

32

33 }

34

35 class Counter {

36 private int value;

37

38 public synchronized int getValue() {

39 return value;

40 }

41

42 public synchronized int increment() {

43 return ++value;

44 }

45

46 public synchronized int decrement() {

47 return --value;

48 }

49 }

輸出結果:

+ View code

static count: 9952

Counter: 10000

AtomicInteger: 10000

countVolatile: 9979

第一行與最后一行,每次運行將得到不同的結果,但是中間兩行的結果相同。

通過上面的例子說明,要解決自增操作在多線程環境下線程不安全的問題,可以選擇使用Java提供的原子類,或者使用synchronized同步方法。

而通過Volatile關鍵字,並不能解決非原子操作的線程安全性。Volatile詳解

三、Java中的自增原理

雖然遞增操作++i是一種緊湊的語法,使其看上去只是一個操作,但這個操作並非原子的,因而它並不會作為一個不可分割的操作來執行。實際上,它包含了三個獨立的操作:讀取count的值,將值加1,然后將計算結果寫入count。這是一個“讀取 - 修改 - 寫入”的操作序列,並且其結果狀態依賴於之前的狀態。

下面寫一個簡單的類,用jdk中的工具javap來反編譯Java字節碼文件。

/**

* @author zhengbinMac

*/

public class TestDemo {

public static int count;

public void code() {

count++;

}

}

localhost:Increment zhengbinMac$ javap -c TestDemo

警告: 二進制文件TestDemo包含Increment.TestDemo

Compiled from "TestDemo.java"

public class Increment.TestDemo {

public static int count;

public Increment.TestDemo();

Code:

0: aload_0

1: invokespecial #1 // Method java/lang/Object."":()V

4: return

public void code();

Code:

0: getstatic #2 // Field count:I

3: iconst_1

4: iadd

5: putstatic #2 // Field count:I

8: return

}

如上字節碼,我們發現自增操作包括取數(getstatic #2)、加一(iconst_1和iadd)、保存(putstatic #2),並不是我們認為的一條機器指令搞定的。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。