我正在准备OCP考试,我在模拟考试中发现了这个问题:
给定:
class Calculator {
private AtomicInteger i = new AtomicInteger();
public void add(int value) {
int oldValue = i.get();
int newValue = oldValue + value;
System.out.print(i.compareAndSet(oldValue,newValue));
}
public int getValue() {
return i.get();
}
}
您可以做些什么来使此类线程安全?
令我惊讶的是,答案是: “类计算器是线程安全的”
一定是我没有正确理解这个概念。据我了解,当所有方法在线程并发下按预期工作时,一个类是线程安全的。现在,如果两个线程同时调用 getValue(),然后调用 add() 传递一个不同的值,然后它们再次调用 getValue(),“第二个”线程将看不到它传递的值增加。
我知道 oldValue 和 newValue 作为局部变量存储在方法堆栈中,但这并不能阻止第二次调用 compareAndSet 会发现 oldValue 不是当前值,因此不会添加新值。
我在这里错过了什么?
最佳答案
根据 JCIP
A class is thread-safe if it behaves correctly when accessed from multiple threads, regardless of the scheduling or interleaving of the execution of those threads by the runtime environment, and with no additional synchronization or other coordination on the part of the calling code.
虽然没有线程安全的定义,也没有类的规范,但在我看来,根据 Calculator
类中 add
方法的任何合理定义,它如果 AtomicInteger i
的值在任何情况下都增加,则“不考虑执行的调度或交错”是“正确的”。
因此,在我看来,根据这个定义,该类不是线程安全的。
关于java - 为什么这段代码线程安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34832475/