首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java与原子类的并发

Java与原子类的并发
EN

Stack Overflow用户
提问于 2018-04-22 16:49:11
回答 2查看 624关注 0票数 5

正如我所知道的,在尝试从多个线程执行相同的操作时,Java并发API的原子类上的操作是一个接一个地执行的,下面的程序的输出对我来说似乎不一致。

代码语言:javascript
复制
public class VisitorCounterAtomic {

    private AtomicInteger visitorCount = new AtomicInteger(0);

    public void visitAndPrint() {
        System.out.println("Total Visitors: " + visitorCount.incrementAndGet());
    }

    public static void main(String... args) {
        ExecutorService service = null;
        VisitorCounterAtomic counter = new VisitorCounterAtomic();

        try {
            service = Executors.newFixedThreadPool(20);
            for (int i = 0; i < 10; i++)
                service.submit(() -> counter.visitAndPrint());
        } finally {
            if (null != service) service.shutdown();
        }
    }
}

输出:

代码语言:javascript
复制
Total Visitors: 1
Total Visitors: 4
Total Visitors: 2
Total Visitors: 5
Total Visitors: 3
Total Visitors: 6
Total Visitors: 7
Total Visitors: 8
Total Visitors: 9
Total Visitors: 10

我的预期输出:

代码语言:javascript
复制
Total Visitors: 1
Total Visitors: 2
Total Visitors: 3
Total Visitors: 4
Total Visitors: 5
Total Visitors: 6
Total Visitors: 7
Total Visitors: 8
Total Visitors: 9
Total Visitors: 10

我知道我可以使用synchronization块生成我的预期输出,但我需要解释为什么不使用原子变量生成预期的输出。

我的推理就像--不管线程执行的顺序如何,它都会在另一个线程增加并打印原子变量的值之前增加和打印。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-04-22 17:00:25

实际订单与AtomicInteger没有任何关系。

AtomicInteger保证可以原子地更新该值。它不能保证线程是按顺序执行的。

实际上,ExecutorService实例以异步方式处理任务。

因此,您无法获得可预测的任务完成顺序。

实际上,在执行incrementAndGet()println()之间有一个竞争条件。

代码语言:javascript
复制
public void visitAndPrint() {        
    System.out.println("Total Visitors: " + visitorCount.incrementAndGet());
}

例如,假设:

  • 线程A执行visitorCount.incrementAndGet() (计数器= 1),但不执行println()
  • 线程A被暂停
  • 线程B执行visitorCount.incrementAndGet() (计数器= 2)和println()
  • 线程A被恢复。执行println()

结果:

访客总数:2 访客总数:1

通过同步该方法,您应该有预期的顺序:

代码语言:javascript
复制
public synchronized void visitAndPrint() {        
    System.out.println("Total Visitors: " + visitorCount.incrementAndGet());
}
票数 5
EN

Stack Overflow用户

发布于 2018-04-22 17:33:43

AtomicInteger类提供原子操作。这意味着它将确保每次只有一个线程对该变量执行操作。它在本质上也是非阻塞。在您的代码中,多个线程同时运行,所以AtomicInteger做得很好,但是哪个线程将首先完成它的任务,而不是依赖于

要解决这个问题,可以使用同步函数来解决这个问题。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49968404

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档