你好,我是多线程的新手.试图理解原子整数的概念.我有一个共享的计数器变量,它按两个线程递增

class MyCounterClass{
    volatile AtomicInteger sharedCounter = new AtomicInteger(0);

    public int incrementCounter() {
        for(int i = 0; i <10000; i++){
            // add 1
            sharedCounter.incrementAndGet();
        }

        return this.sharedCounter.get();
    }
}

public static void main(String[] args) throws InterruptedException {
        MyCounterClass myCounterClassObj = new MyCounterClass();
        Thread t1 = new Thread(() -> {
            System.out.println("Thread " + Thread.currentThread().getName() + " " +myCounterClassObj.incrementCounter());
        });

        Thread t2 = new Thread(() -> {
            System.out.println("Thread " + Thread.currentThread().getName()+ " " + myCounterClassObj.incrementCounter());
        });

        t1.start();
        t2.start();

        t1.join();
        t2.join();
    }
}

我认为我的2个线程的输出将是20000.但是我得到了20000作为一个线程的输出,而另一个线程显示了10000到20000之间的一些随机值. 有人能帮我了解一下这里发生了什么吗?

enter image description here

推荐答案

它显示的不是"一个随机值",而是"一个介于10,000和20,000之间的值".它必须至少是10,000,因为正在打印的线程已经将计数器递增了10,000次,并且它最多必须是10,000,因为other线程将使计数器at most递增10,000次.

如果在both个线程完成所有10,000个增量后,两个线程都达到返回值this.sharedCounter.get(),则只会显示两次20,000.一个线程很可能会比另一个线程先完成一点--此时计数器不会是20,000.

Java相关问答推荐

在Spring Boot中测试时出现SQL语法错误

是否可以从@ TrustMapping中删除特定方法的基路径?

如何从片段请求数据到活动?在主要活动中单击按钮请求数据?

如何将kotlin代码转换为java

如何在Javascript中设置文本区域圆角的样式

@org.springframework.beans.factory.annotation.Autowired(required=true)-注入点有以下注释:-SpringBoot

为什么JAVA&S清洁器使用链表而不是并发HashSet?

具有阻塞方法的开源库是否应该为执行提供异步选项?

与Spring Boot相关的实体未正确保存

SonarLint:只能有条件地调用方法(S)

迁移到Java 17后,日期显示不准确

使用Jackson库反序列化json

Java泛型类方法的静态返回类型是否被类型擦除?

Instancio未在日志(log)中显示测试失败消息

在java中使用不同的application.properties-jar而不使用Spring

模拟JUnit未检测到返回字符串的方法的任何声纳覆盖

通过/失败的参数化junit测试方法执行数

在Java中使用StorageReference将数据从Firebase存储添加到数组列表

java21预览未命名的符号用于try-with-resources

类型安全:从 JSONArray 到 ArrayList> 的未经判断的转换