[英]Flux visibility problems with volatile variable
我有一個簡單的 Spring controller 有一個 Spring 服務作為依賴項。 在服務 class 中,我有一個名為 flag 的 int 類型的 static volatile 字段。 當我通過 controller 調用 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));
}
}
這是控制台中的 output:
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
從 output 可以看出,即使 flag 的值變為 3,它仍會繼續打印消息 Start。一段時間后,打印的消息會更改。 我想有一些緩存或類似的東西,但是 volatile 變量沒有被緩存。
問題是 - 這是一個錯誤還是我錯過了什么?
為一堆元素立即執行生成消費者。 您可以通過在generate
后立即添加日志來輕松確認:
Flux.generate(...).doOnNext(e -> log.info("executed: {}", e))
印刷:
2022-01-20 13:31:50,346 INFO parallel-1 - Flag = 5
2022-01-20 13:31:50,349 INFO parallel-1 - executed: Start
2022-01-20 13:31:50,351 INFO parallel-1 - executed: Start
2022-01-20 13:31:50,351 INFO parallel-1 - executed: Start
2022-01-20 13:31:50,351 INFO parallel-1 - executed: Start
2022-01-20 13:31:50,351 INFO parallel-1 - executed: Start
2022-01-20 13:31:50,351 INFO parallel-1 - executed: Start
2022-01-20 13:31:50,351 INFO parallel-1 - executed: Start
2022-01-20 13:31:50,351 INFO parallel-1 - executed: Start
2022-01-20 13:31:50,351 INFO parallel-1 - executed: Start
2022-01-20 13:31:50,351 INFO parallel-1 - executed: Start
2022-01-20 13:31:50,351 INFO parallel-1 - executed: Start
2022-01-20 13:31:50,351 INFO parallel-1 - executed: Start
2022-01-20 13:31:50,351 INFO parallel-1 - executed: Start
2022-01-20 13:31:50,351 INFO parallel-1 - executed: Start
2022-01-20 13:31:50,351 INFO parallel-1 - executed: Start
2022-01-20 13:31:50,351 INFO parallel-1 - executed: Start
2022-01-20 13:31:50,351 INFO parallel-1 - executed: Start
2022-01-20 13:31:50,351 INFO parallel-1 - executed: Start
2022-01-20 13:31:50,351 INFO parallel-1 - executed: Start
2022-01-20 13:31:50,351 INFO parallel-1 - executed: Start
2022-01-20 13:31:50,351 INFO parallel-1 - executed: Start
2022-01-20 13:31:50,351 INFO parallel-1 - executed: Start
2022-01-20 13:31:50,351 INFO parallel-1 - executed: Start
2022-01-20 13:31:50,351 INFO parallel-1 - executed: Start
2022-01-20 13:31:50,351 INFO parallel-1 - executed: Start
2022-01-20 13:31:50,351 INFO parallel-1 - executed: Start
2022-01-20 13:31:50,351 INFO parallel-1 - executed: Start
2022-01-20 13:31:50,351 INFO parallel-1 - executed: Start
2022-01-20 13:31:50,352 INFO parallel-1 - executed: Start
2022-01-20 13:31:50,352 INFO parallel-1 - executed: Start
2022-01-20 13:31:50,352 INFO parallel-1 - executed: Start
2022-01-20 13:31:50,352 INFO parallel-1 - executed: Start
generate
方法根據下游的需求發出元素。 它首先生成 32 個元素並緩沖它們。 當下游開始處理元素並且緩沖區大小低於閾值時,它會發出更多元素。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.