【发布时间】:2022-01-20 09:50:29
【问题描述】:
我有一个简单的 Spring 控制器,它有一个 Spring 服务作为依赖项。 在服务类中,我有一个名为 flag 的 int 类型的静态 volatile 字段。 当我通过控制器调用 createFlux() 方法时,标志设置为 5,然后创建一个新的 Flux,它每秒检查一次标志,并根据标志值打印一条消息。由于 delayElements 方法语义,代码将并行执行。之后,如果我调用 changeFlag() 方法,该方法会更改标志的值,并且由于标志变量是易变的,我希望打印的消息会发生变化,但这不会发生。
代码如下:
@RestController
public class MyController {
@Autowired private MyService myService;
@GetMapping("createFlux")
public void createFlux() {
myService.createFlux();
}
@GetMapping("changeFlag")
public void changeFlag() {
myService.changeFlag();
}
}
@Service
public class MyService {
private static volatile int flag = 3;
public void changeFlag() {
flag = 3;
System.out.println("############# Flag = " + flag);
}
public void createFlux() {
flag = 5;
System.out.println("Flag = " + flag);
Flux.generate(sink -> {
if (flag == 3) {
sink.next("Stop");
} else {
sink.next("Start");
}
}).delayElements(Duration.ofSeconds(1)).subscribe(s -> System.out.println(Thread.currentThread().getName() + " : " + s));
}
}
这是控制台的输出:
Flag = 5
parallel-1 : Start
parallel-2 : Start
parallel-3 : Start
parallel-4 : Start
############# Flag = 3
parallel-5 : Start
parallel-6 : Start
parallel-7 : Start
parallel-8 : Start
parallel-1 : Start
parallel-2 : Start
parallel-3 : Start
parallel-4 : Start
parallel-5 : Start
parallel-6 : Start
parallel-7 : Start
parallel-8 : Start
parallel-1 : Start
parallel-2 : Start
parallel-3 : Start
parallel-4 : Start
parallel-5 : Start
parallel-6 : Start
parallel-7 : Start
parallel-8 : Start
parallel-1 : Start
parallel-2 : Start
parallel-3 : Start
parallel-4 : Start
parallel-5 : Start
parallel-6 : Start
parallel-7 : Start
parallel-8 : Start
parallel-1 : Stop
parallel-2 : Stop
parallel-3 : Stop
parallel-4 : Stop
parallel-5 : Stop
parallel-6 : Stop
从输出可以看出,即使 flag 的值更改为 3,它也会继续打印消息 Start。一段时间后,打印的消息也发生了变化。我想有一些缓存或类似的东西,但是 volatile 变量没有被缓存。
问题是 - 这是一个错误还是我遗漏了什么?
【问题讨论】:
-
你能不能试着把这个变量变成一个实例变量,看看输出是否改变?
-
没有变化。不管是不是静态的,结果都是一样的。
-
你能把int改成Integer再试一次吗?
-
仍然没有变化。使用 Integer 没有意义,但使用 int 没有意义。
标签: java multithreading project-reactor