Volatile AtomicInteger不工作

时间:2015-07-09 08:16:36

标签: java multithreading

嗨,我正在尝试挥发性。我从我的主线程创建10个线程,并从每个线程打印静态计数器的值。

输出不确定。任何人都可以让我知道为什么它不起作用。

public class Main {
    static AtomicInteger  counter = new AtomicInteger(0);

    public static void main(String[] args) {
        while(counter.getAndIncrement() < 10){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        System.out.println(counter.get());
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    }
}

在此我还尝试将计数器更改为

static volatile int counter = 0;

我得到的输出是

  

3 3 6 6 7 7 10 10 11 11

输出每次都不同。 我不希望它们按正确顺序排列,但我希望0到10之间的唯一值。

2 个答案:

答案 0 :(得分:6)

您有一个增加值的线程,以及获取并显示该值的多个线程。显然,增量线程有很多潜力可以做到这一点,然后其余线程打印相同的值。仅仅因为你调用start()并不意味着线程会在值增加之前运行。

如果您只是在{while循环中放置get(),并在其他主题中使用incrementAndGet(),那么您将获得唯一值(尽管您可能会获得超过10个)。

如果您想打印10个不同的值,则代码无效。

使用原始代码,您可以创建10个线程,但是当它们运行时,它们将打印计数器的当前值。如果3个已启动的线程运行,它们将始终打印相同的值。

当你将get()移动到while循环中时,它可以并且将创建超过10个线程,因为增加计数器的其他线程还没有机会运行,导致线程被创建,直到10个递增线程运行。之后仍有剩余的线程被创建,但还没有运行 - &gt;你得到10 +额外的线程。

如果要使用线程,则无法使用单个计数器变量获得所需的输出。

答案 1 :(得分:4)

致电时

counter.getAndIncrement();

以及后来的另一个线程调用

System.out.println(counter.get());

然后这些价值观彼此无关。

如果要保留值,则需要在不变的变量中执行此操作。

    for (int i = 0; i < 10; i++) {
        final threadId = i;
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(threadId);
            }
        }).start();
    }

不需要使用volatile变量,但如果你真的需要它,你可以做

    for (int i = 0; i < 10; i++) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(counter.getAndIncrement());
            }
        }).start();
    }