簡體   English   中英

volatile 變量的通量可見性問題

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM