簡體   English   中英

Java中Atomic set vs volatile set的區別?

[英]Difference between Atomic set vs volatile set in Java?

說我有以下兩個班級。

public class Foo {
   private volatile Integer x = 0;
   private volatile boolean istrue = false;

   public void setInt(int x) {
       this.x = x;
   }

   public void setBoolean(boolean istrue) {
       this.istrue = istrue;
   }

   public Integer getInt() {
       return x;
   }
}

VS

public class Bar {
   private volatile AtomicInteger x = 0;
   private volatile AtomicBoolean istrue = false;

   public void setInt(int x) {
       this.x.set(x);
   }

   public void setBoolean(boolean istrue) {
       this.istrue.set(istrue);
   }

   public Integer getInt() {
       return this.x.get();
   }
}

假設多個線程可以訪問Foo或Bar。 這兩個類是否安全? 這兩個班的真正區別是什么?

在當前示例中,您在方法中有單個賦值語句。 我想你需要提出一個更好的例子。 因為賦值將在單個指令中執行。 這使得兩個實現線程都安全。 即使兩個不同的線程有可能在訪問它們時看到int不同值,因為到時候,其他線程可能會重置(設置)到不同的值。

看看這個: java中的線程安全是什么?

這兩個類都是編寫的線程安全的。 使用volatile變量和java.util.concurrent.atomic類之間的區別在於原子類允許以原子方式執行更復雜的操作,例如compare和set。 只需直接訪問volatile變量,就可以在compare和set之間進行線程上下文切換,因此在完成set時,不能依賴比較結果仍然有效。

這兩個類都是線程安全的。 但這不是你的問題。

Foo :對字段的讀寫是原子的。 但更復雜的操作,如i ++則不然。 i ++轉換為i = i + 1 ,它分解為讀取和寫入,因此在使整個操作不是原子操作之間可能存在線程上下文切換。

Bar :volatile使得對Atomic字段本身的訪問成為原子,因此您可以使用原子方式使用新引用重新分配字段。 但是像compareAndSetinc這樣的字段上的操作是原子的。 問題是,您是否需要對字段進行原子寫入訪問或僅需要操作的原子性? 由於AtomicXXX類型只是值的容器,因此通常不會重新分配變量,而是重新分配原子的值。

所以這應該足夠了:

private final AtomicInteger x = new AtomicInteger(0);
private final AtomicBoolean istrue = new AtomicBoolean(false);

暫無
暫無

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

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