Почему синхронизированный геттер работает как волатильное чтение? - PullRequest
0 голосов
/ 16 января 2019

Эта программа не завершается!

public class Main extends Thread {
  private int i = 0;
  private int getI() {return i; }
  private void setI(int j) {i = j; }

  public static void main(String[] args) throws InterruptedException {
    Main main = new Main();
    main.start();

    Thread.sleep(1000);
    main.setI(10);
  }

  public void run() {
    System.out.println("Awaiting...");
    while (getI() == 0) ;
    System.out.println("Done!");
  } 
}

Я понимаю, что это происходит потому, что ядро ​​ЦП, работающее в цикле Awaiting, всегда видит кэшированную копию i и пропускает обновление.

Я также понимаю, что если я сделаю volatileprivate int i = 0;, тогда while (getI()... будет вести себя [1] , как будто каждый раз, когда он обращается к основной памяти - так он увидит обновленное значение и моя программа прекратит работу.

Мой вопрос: Если я сделаю

synchronized private int getI() {return i; }

Это удивительно работает !! Программа завершается.

Я понимаю, что synchronized используется для предотвращения одновременного входа в метод двух разных потоков, но здесь только один поток, который когда-либо входит в getI(). Так что это за колдовство?

Редактировать 1

Это (синхронизация) гарантирует, что изменения состояния объекта видны всем потокам

Таким образом, вместо того, чтобы напрямую иметь поле частного состояния i, я сделал следующие изменения:

Вместо private int i = 0; Я сделал private Data data = new Data();, i = j изменен на data.i = j и return i изменен на return data.i

Теперь методы getI и setI ничего не делают для состояния объекта, в котором они определены (и могут быть синхронизированы). Даже сейчас использование ключевого слова synchronized приводит к завершению программы! Самое интересное в том, что у объекта, состояние которого действительно изменяется (Data), нет синхронизации или чего-либо встроенного в него. Тогда почему?


[1] Это, вероятно, будет просто вести себя , поскольку то, что на самом деле происходит, мне неясно

1 Ответ

0 голосов
/ 16 января 2019

Это просто совпадение или платформа, или конкретная JVM, она не гарантируется JLS.Так что не зависите от этого.

...