这是学校的任务,但我确实需要一些帮助。我无法终生弄清楚为什么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作为输出。


incrementAndGetget不同。
因此,具有相同值的代码将返回不同的输出。
一种是先增加值然后检查条件,另一种是先检查值然后执行操作。

即使if(变量> MAX_VALUE)中的代码也将导致不同的输出。

因此,这与线程安全无关。

关于java - 计数器的线程安全与非线程安全实现,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40690100/

10-12 05:24