简体   繁体   English

Java中Atomic set vs volatile set的区别?

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

say I have the following two classes. 说我有以下两个班级。

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 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();
   }
}

Assume multiple threads can access Foo or Bar. 假设多个线程可以访问Foo或Bar。 Are both classes thread safe? 这两个类是否安全? what is the difference between the two classes really? 这两个班的真正区别是什么?

In the current example you have single assignment statements in the methods. 在当前示例中,您在方法中有单个赋值语句。 I think you need to come up with a better example. 我想你需要提出一个更好的例子。 Because the assignment will be executed in a single instruction. 因为赋值将在单个指令中执行。 Which makes both the implementation thread safe. 这使得两个实现线程都安全。 Even though, it is possible that, two different threads see different values of the int when they access them, because by the time, other thread can potentially reset (set) to a different value. 即使两个不同的线程有可能在访问它们时看到int不同值,因为到时候,其他线程可能会重置(设置)到不同的值。

Check this out: What is thread Safe in java? 看看这个: java中的线程安全是什么?

Both classes are thread safe as written. 这两个类都是编写的线程安全的。 The difference between use of a volatile variable and the java.util.concurrent.atomic classes is that the atomic classes permit more complex operations, such as compare and set, to be performed atomically. 使用volatile变量和java.util.concurrent.atomic类之间的区别在于原子类允许以原子方式执行更复杂的操作,例如compare和set。 With just direct access to a volatile variable, there could be a thread context switch between the compare and the set, so you can't rely on the result of the compare still being valid when the set is done. 只需直接访问volatile变量,就可以在compare和set之间进行线程上下文切换,因此在完成set时,不能依赖比较结果仍然有效。

Both classes are thread safe. 这两个类都是线程安全的。 But that is not your issue here. 但这不是你的问题。

Foo : reads and writes to the fields are atomic. Foo :对字段的读写是原子的。 But more complex operations such as i++ are not. 但更复杂的操作,如i ++则不然。 i++ translates to i = i + 1 , which decomposes to a read and a write, so there could a thread context switch in between making the entire operation not atomic. i ++转换为i = i + 1 ,它分解为读取和写入,因此在使整个操作不是原子操作之间可能存在线程上下文切换。

Bar : the volatile makes the access to the Atomic fields themselves atomic, so you can reassign the fields with new references in an atomic ways. Bar :volatile使得对Atomic字段本身的访问成为原子,因此您可以使用原子方式使用新引用重新分配字段。 The operations on the fields like compareAndSet or inc however are atomic. 但是像compareAndSetinc这样的字段上的操作是原子的。 Question is, do you need atomic write access to the fields or just atomicity on the operations? 问题是,您是否需要对字段进行原子写入访问或仅需要操作的原子性? As the AtomicXXX type are just containers for for values, you typically don't reassign the variable, but reassign values, which is atomic. 由于AtomicXXX类型只是值的容器,因此通常不会重新分配变量,而是重新分配原子的值。

So this should be sufficient: 所以这应该足够了:

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