这个类是线程安全的吗?
是否可以看到不一致的值?让我们说最初的值为80.线程1调用setA(100)
并进入函数但尚未调用a.set(100)
并且线程2同时调用getA()
。线程2是否可以看到80?
public class A {
private AtomicInteger a;
public int getA() {
return a.get()
}
public void setA(int newVal){
a.set(newVal);
}
}
我知道同步它会保证线程2看到100,但AtomicInteger不确定。
答案 0 :(得分:10)
这个类是否是线程安全的?
是的。
线程1调用setA(100)并进入该函数但尚未调用a.set(100)并且线程2同时调用getA()。线程2有可能看到80吗?
是。在同步AtomicInteger
内的volatile字段的内存屏障代码完成之前,竞争条件可以显示80或100。
线程1甚至可以进入AtomicInteger.set
方法并且在内部字段赋值之前,但仍然可以通过get AtomicInteger.get
方法返回80.
时,无法保证在其他线程中更新值。保证的是当get()
完成时,您获得最新的同步值,当set()
完成时,所有其他线程将看到更新。
不能保证不同线程中getter和setter调用的 timing 。
答案 1 :(得分:1)
正如@Gray指出的那样,这里可能存在竞争条件。
调用get
然后调用set
不是原子操作。 The Atomic*
classes提供无锁原子条件更新操作compareAndSet
- 您应该使用该操作来保证线程安全。