AtomicInteger不会同时增加

dab*_*aba 4 java concurrency multithreading

我正在测试该类的使用,AtomicInteger但增量似乎并未在互斥控制下应用.

这是我的测试:

static class AtomicIntegerRunnable implements Runnable
{
    private static AtomicInteger x;

    AtomicIntegerRunnable() {}

    AtomicIntegerRunnable(AtomicInteger x) 
    {
        this.x = x;
    }

    @Override
    public void run()
    {
        System.out.println(x.get());
        x.getAndIncrement();
    }
}

public static void main(String[] args) {
    ExecutorService e = Executors.newFixedThreadPool(n_whatever);
    AtomicInteger x = new AtomicInteger();
    int n = 10;
    for (int i=0; i<n; i++) {
        e.submit(new AtomicIntegerRunnable(x));
            }
    e.shutdown();
    while (!e.isTerminated());
}
Run Code Online (Sandbox Code Playgroud)

在印刷品中,我得到了类似的东西

0 0 1 1 1 5 4 3 2 6

代替

0 1 2 3 4 5 6 7 8 9

.怎么了?

编辑 @Louis Wasserman

static class AtomicIntegerRunnable implements Runnable
{
    private AtomicInteger x;

    AtomicIntegerRunnable() {}

    AtomicIntegerRunnable(AtomicInteger x) 
    {
        this.x = x;
    }

    @Override
    public void run()
    {
        x.getAndIncrement();
    }
}

public static void main(String[] args) 
{
    ExecutorService e = Executors.newFixedThreadPool(n_whatever);
    AtomicIntegerRunnable x = new AtomicIntegerRunnable(new AtomicInteger());
    int n = 10;
    for (int i=0; i<n; i++) 
        e.submit(x);
    e.shutdown();
    while (!e.isTerminated());
}
Run Code Online (Sandbox Code Playgroud)

Nic*_*ole 10

你得到它并在两个单独的动作中递增它.您正在打印第一个,这使您自己的代码非原子.

每个AtomicInteger操作本身都是原子的,但你不能按顺序使用两个并考虑原子组合 - 通过定义,两个操作不是原子的.

解决这个问题:

@Override
public void run()
{
    System.out.println(x.getAndIncrement());
}
Run Code Online (Sandbox Code Playgroud)

但是,正如评论中指出的那样,你有第三个动作,即打印.增量操作也不是原子的.因此,您需要同步这两个才能使列表按顺序打印出来.

你可以调用那个方法printAndIncrement.

通常AtomicInteger用于确保多线程代码永远不会意外地在同一个整数上运行,而不是确保外部系统(如输出缓冲区)按顺序看到这些增量(因为您还需要其他东西来同步与外部系统的通信) ).

  • 它们仍然不一定会被订购. (5认同)
  • 打印是一个单独的行动.所以线程一可能得到值`1`,上下文切换,线程二得到值`2`并先打印,然后打印一个线程. (5认同)