线程安全与非线程安全的计数器实现

时间:2016-11-19 06:56:53

标签: java multithreading synchronization thread-safety atomic

这是一项学校作业,但我真的需要一些帮助。我不能为我的生活弄清楚为什么两个不同版本的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;
    }
}

3 个答案:

答案 0 :(得分:1)

假设值为:MIN_VALUE = -1,MAX_VALUE = 3,counter = 3.

代码1:

synchronized (lock) {                       
                next = counter.incrementAndGet();   
                if (next> MAX_VALUE) {                  
                    counter.set(MIN_VALUE); 
                    resetCounter.incrementAndGet();
                    next = MIN_VALUE;
                }

            }
  1. 它递增计数器的值,然后将其用于比较。
  2. 因此,next的值变为4. if(next > MAX_VALUE)变为if(4> 3),这会将next的值更改为-1并返回它。
  3. 代码2:

    synchronized (lock) {
                    int i = counter.get();
                    if (i > MAX_VALUE) {
                        counter.set(INITIAL_VALUE);
                        resetCounter.incrementAndGet();
                    }
                    next = counter.incrementAndGet();
                }
    
    1. 它将值分配给计数器然后进行比较。
    2. i的值仍然是3. if(i > MAX_VALUE)变为if(3> 3),其中不是返回3作为输出。
    3. incrementAndGetget不同。 所以具有相同值的代码返回不同的输出。 一个是首先递增值然后检查条件,另一个是先检查值然后再执行一个操作。

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

      所以这与线程安全无关。

答案 1 :(得分:0)

认为两种方法在逻辑上都是线程安全的。因为在两种方法中都使用了synchronized。和synchronized块用于线程安全。

答案 2 :(得分:0)

两者都是线程安全的。也许你可以粘贴代码如何测试它们。问题可能在那里。

相关问题