我试图通过递增Executor服务任务中的计数并使用倒计时锁存来等待所有线程启动和停止,然后在读取主线程中的值之前,来模拟一个非线程安全的计数器类.

问题是,当我运行它时,最后的System.out总是返回10作为正确的计数值.当我运行它时,我希望看到一些其他的值,因为这10个线程可能会看到不同的值.

我的代码如下.知道这里发生了什么吗?我在Java 17和IntelliJ Idea上运行它.

Couner.java

public class Counter {

    private int counter = 0;

    public void incrementCounter() {
        counter += 1;
    }

    public int getCounter() {
        return counter;
    }
}

#Main.Java#

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Main {
    public static void main(String[] args) throws InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(10);

        CountDownLatch startSignal = new CountDownLatch(10);
        CountDownLatch doneSignal = new CountDownLatch(10);
        Counter counter = new Counter();
        for (int i=0; i<10; i++) {
            executorService.submit(() -> {
                try {
                    startSignal.countDown();
                    startSignal.await();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }

                counter.incrementCounter();
                doneSignal.countDown();
            });
        }

        doneSignal.await();
        System.out.println("Finished: " + counter.getCounter());
        executorService.shutdownNow();
    }
}

推荐答案

值得记住的是,尽管有些东西没有正确同步,但它在某些情况下仍然可以正确运行,只是在每种情况下、在每个JVM上、在每个硬件上都这样做并不是百分之百.

换句话说,没有反向保证,例如,优化器可以自由地决定您的代码可以用正确同步的实现以很少的成本甚至是零成本进行替换.

(乍一看,这是否是这里真正发生的事情对我来说并不明显.)

Java相关问答推荐

无法在Java中将hhmmss格式的时间解析为LocalTime

使用Apache Poi MQLSlideShow,在XSLFTable表中,我们可以在文本段落后面的每个单元格中包含圆角矩形吗?

如何为具有多对多关系的实体的给定SQL查询构建JPA规范?

当我用OkHttpClient重写shouldInterceptRequest来发布数据时,Android WebView正在以纯HTML加载URL内容

Cucumber TestNG Assert失败,出现java. lang. Numbercycle异常

只需最少的代码更改即可将版本号标记添加到日志(log)

使用REST客户端和对象映射器从字符串反序列化Json

使用Spring Boot3.2和虚拟线程的并行服务调用

如何使用值中包含与号的查询参数创建一个java.net.URI

如何从错误通道回复网关,使其不会挂起

为什么Java编译器不区分不同类型的方法?

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

当Volatile关键字真的是必要的时候?

try 使用Spring集成和MySQL实现发件箱模式时,锁定等待超时

如何配置空手道以使用FeignClient或RestTemplate代替ApacheHttpClient

如何使用MapStrCut转换双向链接

Java中HashSet的搜索时间与TreeSet的搜索时间

插入中的JOOQ序列,设置为VS值

在输入端没有可行的替代方案'; Select *';

单例模式中热切初始化和惰性初始化的区别