在多个线程中更新AtomicInteger变量时未获得预期结果

问题描述 投票:1回答:1

在此代码中,我正在使用10个线程更新AtomicInteger变量。我希望Counter.getInstance()。holder.n的最终结果为1000000,但它会打印出991591之类的随机数。我的代码有什么问题?

public class Test {


    public static void main(String[] args) {

        List<Thread> list = new ArrayList<Thread>();
        for (int i = 0; i < 10; i++) {
            list.add(new Thread() {

                public void run() {
                    for (int i = 0; i < 100000; i++) {
                        Counter.getInstance().holder.n.incrementAndGet();
                    }
                }
            });
        }
        for (Thread thread : list) {
            thread.start();
        }

        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(Counter.getInstance().holder.n);


    } 
} 

class Counter {
    private static Counter counter;
    Holder holder = new Holder();


    public static Counter getInstance() {
        if (counter == null) {
            counter = new Counter();
        }
        return counter;
    }
    class Holder {
        AtomicInteger n = new AtomicInteger(0);
    } 
}
java multithreading concurrency thread-safety atomicinteger
1个回答
1
投票

您在这里有两个主要的并发问题:

  1. 您不必等待每个Thread正确完成工作。有多种实现方法,最简单的方法是使用Thread.join()
  2. 您的单例实现似乎不正确。我想您打算用一个内部类实现它。似乎answer可以帮助您了解此处发生的情况。

这里是看起来或多或少正确的实现。

class Test {
    public static void main(String[] args) throws InterruptedException {

        List<Thread> list = new ArrayList<Thread>();
        for (int i = 0; i < 10; i++) {
            list.add(new Thread() {

                public void run() {
                    for (int i = 0; i < 100000; i++) {
                        Counter.getInstance().n.incrementAndGet();
                    }
                }
            });
        }
        for (Thread thread : list) {
            thread.start();
        }

        for (Thread thread : list) {
            thread.join();
        }

        System.out.println(Counter.getInstance().n);
    }
}

class Counter {
    public AtomicInteger n = new AtomicInteger(0);

    public static Counter getInstance() {
        return Holder.instance;
    }
    private static class Holder {
        private static final Counter instance = new Counter();
    }
}

您也可以使用类似CountDownLatch的名称。例如:

final int count = 10;
CountDownLatch latch = new CountDownLatch(count);
List<Thread> list = new ArrayList<Thread>();
for (int i = 0; i < count; i++) {
    list.add(new Thread() {

        public void run() {
            for (int i = 0; i < 100000; i++) {
                Counter.getInstance().n.incrementAndGet();
            }
            latch.countDown();
        }
    });
}
for (Thread thread : list) {
    thread.start();
}

latch.await();

System.out.println(Counter.getInstance().n);
© www.soinside.com 2019 - 2024. All rights reserved.