簡體   English   中英

如何在java.util.concurrent.atomic包中定義的類中實現原子性?

[英]How atomicity is achieved in the classes defined in java.util.concurrent.atomic package?

to find out how atomicity is achieved by the atomic operations provided by the class. 我正在瀏覽的源代碼,以了解如何通過類提供的原子操作實現原子性。 method source is as follows 例如方法源如下

public final int getAndIncrement() {
    for (;;) {
        int current = get();
        int next = current + 1;
        if (compareAndSet(current, next))
            return current;
    }
}

我無法理解在無限for循環中編寫操作序列的目的。 它在Java Memory Model(JMM)中是否有任何特殊用途。 請幫我找一個描述性的理解。 提前致謝。

我無法理解在無限for循環中編寫操作序列的目的。

此代碼的目的是確保volatile字段得到適當更新, 而不會產生synchronized鎖的開銷。 除非有大量的線程都在競爭更新同一個字段,否則很可能會旋轉很多次來實現這一目標。

volatile關鍵字提供可見性和內存同步保證,但本身並不能確保具有多個操作(測試和設置)的原子操作。 如果您正在測試然后設置volatile字段,那么如果多個線程試圖同時執行相同的操作,則存在競爭條件。 在這種情況下,如果多個線程試圖同時遞增AtomicInteger ,您可能會錯過其中一個增量。 這里的並發代碼使用自旋循環和compareAndSet底層方法,以確保volatile int僅更新為4(例如),如果它仍然等於3。

  1. t1獲取atomic-int,它為0。
  2. t2獲取原子int,它為0。
  3. t1加1
  4. t1 原子測試以確保它為0,它是,並存儲1。
  5. t2加1
  6. t2 原子測試以確保它為0,它不是 ,所以它必須旋轉並再次嘗試。
  7. t2得到atomic-int,它是1。
  8. t2加1
  9. t2 原子測試以確保它是1,它 ,並存儲2。

它在Java Memory Model(JMM)中是否有任何特殊用途。

不,它服務於類和方法定義的目的,並使用 JMM和volatile周圍的語言定義來實現其目的。 JMM定義了語言對synchronizedvolatile和其他關鍵字的作用,以及多個線程如何與緩存和中央內存交互。 這主要是關於與操作系統和硬件的本機代碼交互,並且很少(如果有的話)關於Java代碼。

它是compareAndSet(...)方法,它通過調用Unsafe類來接近JMM,而Unsafe類主要是帶有一些包裝器的本機方法:

public final boolean compareAndSet(int expect, int update) {
    return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}

我無法理解在無限for循環中編寫操作序列的目的。

為了理解為什么它處於無限循環中,我發現理解compareAndSet作用以及它如何返回false是有幫助的。

 Atomically sets the value to the given updated value if the current value == the expected value. Parameters: expect - the expected value update - the new value Returns: true if successful. False return indicates that the actual value was not equal to the expected value 

所以你閱讀了Returns消息並詢問它是如何可能的?

如果兩個線程在接近同一時間調用incrementAndGet ,則它們都進入並看到值current == 1 兩個線程都將創建一個線程本地的next == 2並嘗試通過compareAndSet進行設置。 根據文檔只有一個線程會獲勝,失敗的線程必須再次嘗試。

這就是CAS的工作原理。 如果失敗,則嘗試更改值,如果成功則再試一次,然后繼續。

現在簡單地將字段聲明為volatile是行不通的,因為遞增不是原子的 所以這樣的事情對我解釋的場景來說並不安全

volatile int count = 0;

public int incrementAndGet(){
   return ++count; //may return the same number more than once.
}

Java的compareAndSet基於CPU比較和交換(CAS)指令,請參閱http://en.wikipedia.org/wiki/Compare-and-swap 它將內存位置的內容與給定值進行比較,並且只有它們相同時,才將該內存位置的內容修改為給定的新值。

在incrementAndGet的情況下,我們讀取當前值並調用compareAndSet(current, current + 1) 如果它返回false,則意味着另一個線程干擾並更改了當前值,這意味着我們的嘗試失敗了,我們需要重復整個循環直到成功。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM