Можно ли описать результат JCStress как результат кэширования, а не переупорядочения?

Я изменил один из примеров JCStress :

      @JCStressTest
@Outcome(id = "0, 0", expect = ACCEPTABLE, desc = "Doing both reads early.")
@Outcome(id = "1, 1", expect = ACCEPTABLE, desc = "Doing both reads late.")
@Outcome(id = "1, 0", expect = ACCEPTABLE, desc = "First is visible but not second.")
@Outcome(id = "0, 1", expect = ACCEPTABLE_INTERESTING, desc = "Second is visible but not first.")
@State
public class Reordering {
    int first;
    int second;

    @Actor
    public void actor1() {
        first = 1;
        second = 1;
    }

    @Actor
    public void actor2(II_Result r) {
        r.r2 = second;
        r.r1 = first;
    }
}

что дало мне следующий результат:

Приемлемые результаты легко понять, но у меня есть несколько вопросов относительно интересного результата . Насколько я понял, JVM может оптимизировать код и изменить порядок инструкций, что означает, что первую функцию можно примерно перевести так:

      public void actor1() {
    second = 1;
    first = 1;
}

что могло бы объяснить, почему был достигнут интересный результат. Мой вопрос: возможно ли, что интересный результат был достигнут не за счет переупорядочения кода, выполненного JVM, а за счет «кэширования»firstи не делать его видимым для запущенного потокаactor2метод, поскольку поле не было нестабильным? Под кэшированием я говорю о сохранении его в регистре/буфере хранения ЦП и о том, чтобы сделать его невидимым для другого потока.

1 ответ

На X86 магазины нельзя переупорядочить с другими хранилищами, а загрузки нельзя переупорядочить с другими загрузками (переупорядочить можно только более старый магазин и новую загрузку на другой адрес). Так что если компилятор не напутает порядок, то на X86 это не может не сработать. Это связано с сильной моделью памяти X86: TSO (Total Store Order).

Однако если вы выберете процессор с более слабой моделью памяти, например ARM или RISC-V, такое переупорядочение может произойти.

Другие вопросы по тегам