我正在尝试测试,出现多线程并发问题。
我期望结果应该小于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 有什么魔法吗?
如果您问为什么添加 print 语句会导致程序“成功”,那是(可能)因为 print 正在共享输出流数据结构上进行一些底层同步。 这将改变您正在测试的代码的行为,并且可能足以“治愈”您正在尝试测试的内存可见性异常。