这是一项学校作业,但我确实需要一些帮助。我一生都无法弄清楚为什么 nextValue()
的两个不同版本的行为不同 - 一个是线程安全的,另一个不是。有人至少可以给我一些正确方向的指示吗?
我已将这两个版本包含在下面的同一类中,但显然它们并不同时出现在代码中......
public class NumGenerator {
static final int MIN_VALUE = -256;
static final int MAX_VALUE = 255;
static final int INITIAL_VALUE = MIN_VALUE -1;
private final AtomicInteger counter = new AtomicInteger(INITIAL_VALUE);
private final AtomicInteger resetCounter = new AtomicInteger(0);
private final Object lock = new Object();
// Thread safe
public int nextValue() {
int next = counter.incrementAndGet();
if (next > MAX_VALUE) {
synchronized (lock) {
next = counter.incrementAndGet();
if (next> MAX_VALUE) {
counter.set(MIN_VALUE);
resetCounter.incrementAndGet();
next = MIN_VALUE;
}
}
}
return next;
}
// Non thread safe
public int nextValue() {
int next = counter.incrementAndGet();
if (next > MAX_VALUE) {
synchronized (lock) {
int i = counter.get();
if (i > MAX_VALUE) {
counter.set(INITIAL_VALUE);
resetCounter.incrementAndGet();
}
next = counter.incrementAndGet();
}
}
return next;
}
}
最佳答案
假设值为:MIN_VALUE = -1、MAX_VALUE = 3、计数器 = 3。
代码 1:
synchronized (lock) {
next = counter.incrementAndGet();
if (next> MAX_VALUE) {
counter.set(MIN_VALUE);
resetCounter.incrementAndGet();
next = MIN_VALUE;
}
}
- 它增加计数器的值,然后将其用于比较。
- 因此 next 的值变为 4。
if(next > MAX_VALUE)
变为 if(4>3) 这会将 next 的值更改为 -1 并返回它。
代码2:
synchronized (lock) {
int i = counter.get();
if (i > MAX_VALUE) {
counter.set(INITIAL_VALUE);
resetCounter.incrementAndGet();
}
next = counter.incrementAndGet();
}
- 它将值分配给计数器然后进行比较。
i
的值仍为 3。if(i > MAX_VALUE)
变为 if(3 > 3),但它不会返回 3 作为输出。
incrementAndGet
和 get
是不同的。
因此具有相同值的代码返回不同的输出。
一种是先增加值,然后检查条件,另一种是先检查值,然后执行操作。
即使 if(variable > MAX_VALUE) 内的代码也会导致不同的输出。
所以这与线程安全无关。
关于java - 计数器的线程安全与非线程安全实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40690100/