首页 > 解决方案 > Java 多线程计数器不工作

问题描述

我正在尝试 Java 多线程计数器。我首先尝试在没有任何同步的情况下观察竞态条件。但是我的计数器没有被工作线程增加。

代码 - 主要方法

public static void main(String... args) {

    System.out.println("Program started");
    Integer sum = 0;
    System.out.println("Initial Sum : " + sum);

    for (int i = 0; i < 100; i++) {
        WorkerThread workerThread = new WorkerThread(sum, i);
        workerThread.run();
    }

    System.out.println("Final Sum : " + sum);

}

代码 - WorkerThread 类

public class WorkerThread implements Runnable {

    private Integer localSum;


    public WorkerThread(Integer sum, int i){
        localSum = sum;
        System.out.println(localSum);
    }

    @Override
    public void run() {
        localSum += 1;
    }
}

我想知道为什么递增localSum不会影响 Integer wrapper object sum。该sum值保持在 0。谁能帮我弄清楚如何将 Integer 包装器传递到线程中并增加原始值?

标签: javamultithreadinginteger

解决方案


问题是它localSum += 1没有做你认为它做的事情。

Integer对象是不可变的:您不能更改Integer. 该localSum+=1语句创建一个 Integer实例,并将localSum变量更改为引用新实例。同时,main()例程的sum变量总是引用原始的、不可变的实例。

@Murat Karagöz 说,“使用AtomicInteger.” 这将解决两个问题;

  1. AtomicInteger实例可变的,并且
  2. ai.incrementAndGet()操作和其他AtomicInteger操作是线程安全的。

您的程序,如所写,不需要线程安全,但是一旦您更改它以实际创建多个线程,就需要它。

AtomicInteger如果您制作所有变量,它将帮助您正确处理final。例如;

public class WorkerThread implements Runnable {
    private final AtomicInteger localSum;

    public WorkerThread(AtomicInteger sum, int i){
        localSum = sum;
        System.out.println(localSum.get());
    }
    ...
}

您不想意外更改localSum字段的值(即,您不想更改AtomicInteger它指向的实例) 您想改变AtomicInteger实例本身。


推荐阅读