Java多线程并发问题不会出现并自动同步

问题描述 投票:0回答:1

我正在尝试测试,出现多线程并发问题。

我期望结果应该小于0,因为它不同步。 但下面的测试失败了。

import static org.assertj.core.api.Assertions.assertThat;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.junit.jupiter.api.Test;

class OptionTest {

    static class Option {

        private int quantity;

        public Option(int quantity) {
            this.quantity = quantity;
        }

        public int getQuantity() {
            return quantity;
        }

        public boolean subtract(int quantity){
            if(quantity >= this.quantity){
                return false;
            }

            // System.out.println("quantity = " + quantity);
            this.quantity -= quantity;
            return true;
        }
    }

    @Test
    void asyncSubtract() throws InterruptedException {
        int numberOfThreads = 100; // Increased number of threads
        ExecutorService executorService = Executors.newFixedThreadPool(numberOfThreads);
        List<Callable<Boolean>> tasks = new ArrayList<>();

        Option option = new Option(201);
        for (int i = 0; i < numberOfThreads; i++) {
            tasks.add(() -> option.subtract(50));
        }

        executorService.invokeAll(tasks);
        executorService.shutdown();

        assertThat(option.getQuantity()).isLessThan(1);
    }
}

在subtract方法中添加打印数量后,就通过了。

import static org.assertj.core.api.Assertions.assertThat;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.junit.jupiter.api.Test;

class OptionTest {

    static class Option {

        private int quantity;

        public Option(int quantity) {
            this.quantity = quantity;
        }

        public int getQuantity() {
            return quantity;
        }

        public boolean subtract(int quantity){
            if(quantity >= this.quantity){
                return false;
            }

            System.out.println("quantity = " + quantity);
            this.quantity -= quantity;
            return true;
        }
    }

    @Test
    void asyncSubtract() throws InterruptedException {
        int numberOfThreads = 100; // Increased number of threads
        ExecutorService executorService = Executors.newFixedThreadPool(numberOfThreads);
        List<Callable<Boolean>> tasks = new ArrayList<>();

        Option option = new Option(201);
        for (int i = 0; i < numberOfThreads; i++) {
            tasks.add(() -> option.subtract(50));
        }

        executorService.invokeAll(tasks);
        executorService.shutdown();

        assertThat(option.getQuantity()).isLessThan(1);
    }
}

谁能解释一下这段代码的执行结果吗? JVM 有什么魔法吗?

java multithreading concurrency java.util.concurrent
1个回答
0
投票

如果您问为什么添加 print 语句会导致程序“成功”,那是(可能)因为 print 正在共享输出流数据结构上进行一些底层同步。 这将改变您正在测试的代码的行为,并且可能足以“治愈”您正在尝试测试的内存可见性异常。

© www.soinside.com 2019 - 2024. All rights reserved.