Неустойчивые поля и локальные объекты не удаляются - PullRequest
0 голосов
/ 07 мая 2020

Рассмотрим следующий фрагмент кода


class Person {
    private final String firstName;
    private final String lastName;

    Person(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    String getFirstName() {
        return this.firstName;
    }

    String getLastName() {
        return this.lastName;
    }

}

class PersonPrinter {

    private Person person;

    void print() {
        Person p = this.person;
        System.err.println(p.getFirstName());
        System.err.println(p.getLastName());
    }

    void setPeron(Person person) {
        this.person = person;
    }

}

Представьте, что есть одновременные вызовы методов setPerson() и print несколькими потоками в одном экземпляре PersonPrinter.

Потому что код не синхронизирован должным образом, JVM может вносить оптимизацию, пока сохраняется семантика « as if serial ».

В частности, метод print() может переупорядочиваться как:

    void print() {
        System.err.println(this.person.getFirstName());
        System.err.println(this.person.getLastName());
    }

Это удаление локальной переменной в пользу прямого доступа к полю: это не изменит семантику одного потока. Конечно, такая оптимизация может привести к распечатке имени одного человека и фамилии другого (поскольку другой параллельный поток может вызывать setPerson()).

У меня такое ощущение, что отметка поля person as volatile в PersonPrinter решит проблему и предотвратит удаление локального (следовательно, гарантируя, что мы печатаем firstName и lastName одного и того же человека) .... но я не смог найти причину, почему это так в oracle docs: если посмотреть на правила модели памяти java, что мешает удалить локальных пользователей в пользу прямого доступа к изменчивому полю?

...