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

标签 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;
    }
}

最佳答案

假设值为: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;
                }

            }
  1. 它增加计数器的值,然后将其用于比较。
  2. 因此 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();
            }
  1. 它将值分配给计数器然后进行比较。
  2. i 的值仍为 3。if(i > MAX_VALUE) 变为 if(3 > 3),但它不会返回 3 作为输出。

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

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

所以这与线程安全无关。

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

相关文章:

swift - 等待任务完成

c++ - 多线程导致分段违规

c - OpenMP - 如何高效同步字段更新

java - Thread#join() 是否让其他线程通过同步块(synchronized block)?

Java 扩展应用程序类加载器?

java - 无法在 intellij idea 中使用 gradle 构建 javafx 项目

Java - 按字节下载图像下载损坏的图像

Java 8 : Kill/Stop a thread after certain period of time

android - MobileServicePushFailedException Azure Android

java - 如何在 Java HTTP Client 中设置套接字超时