【问题标题】:Java threadsafe counter out of boundJava 线程安全计数器越界
【发布时间】:2018-09-27 21:54:48
【问题描述】:

我想实现简单的线程安全计数器。数字顺序正确,所以部分没问题,唯一的问题是条件并不总是满足,有时数字会上升到 51 或 52。

我是否应该在 while 循环周围也使用同步标签?

我的意思是,我可以仔细检查并在 printAndIncrement 方法中添加一个条件,但这似乎不太优雅。

public class MyCounter implements Runnable {

    static int currentValue = 0;

    private static synchronized void printAndIncrement() {
        System.out.print(Thread.currentThread().getName() + ": " + currentValue + "\n");
        currentValue++;
    }

    @Override
    public void run() {
        while (currentValue <= 50) {
            printAndIncrement();
        }
    }

    public static void main(String[] args) {
        MyCounter counter = new MyCounter();
        Thread thread1 = new Thread(counter);
        Thread thread2 = new Thread(counter);
        Thread thread3 = new Thread(counter);
        thread1.start();
        thread2.start();
        thread3.start();
    }
}

【问题讨论】:

标签: java multithreading


【解决方案1】:

检查currentValue &lt;= 50 和调用printAndIncrement 必须在同一个同步块中。否则会出现这个问题。

currentValue 为50。三个线程都可以检查当前值不超过50,然后尝试同时调用printAndIncrement();

由于synchronized void printAndIncrement(),线程将按顺序执行此方法,但对于第一个线程,currentValue 将是 50,对于第二个线程,它将是 51,对于第三个线程,它将是 52。

【讨论】:

    【解决方案2】:

    问题在于您的边界检查和增量不是两者同步,这完全破坏了同步点。

    我可以建议同时允许同步读取/更新并允许您的循环停止的最佳替代方法是使递增方法返回一个布尔值:

    /** Prints and increments, returning true if max value has not been reached */
    private static synchronized boolean printAndIncrement() {
        if(currentValue < 51) {
            System.out.print(Thread.currentThread().getName() 
                 + ": " + currentValue + "\n");
            currentValue++;
    
            return true;
        } else {
            return false;
        }
    }
    

    并将运行方法更改为:

    public void run() {
        while (printAndIncrement()) {
            //nothing needs to be done here
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-07-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多