Java 线程安全计数器越界

标签 java multithreading

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

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

我的意思是,我可以仔细检查并在方法 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();
    }
}

最佳答案

支票currentValue <= 50并调用printAndIncrement必须在同一个同步块(synchronized block)中。否则就会出现这个问题。

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

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

关于Java 线程安全计数器越界,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49886447/

相关文章:

java - Java中如何统一处理 "Exception or null"的情况?

c++ - 这种基于线程 ID 的同步是否安全整洁?

c++ - Qt在主线程中获取线程ID?

c - 关于 _mm_clflush (void const* p)

java - do while 循环在我不希望它循环时循环

java - 在 Eclipse 中生成 java 代理类

java - 如何从java中的方法返回List<Long>值并将其放入新列表中?

java - 如何自定义 PriorityQueue.stream().foreach 以按优先顺序迭代

c - 当线程执行for循环迭代时如何继续与master一起工作?

c - 如何安全地将 for 循环与内部的 memcpy 并行