Как возникают проблемы с видимостью в параллелизме Java?

Я читаю книгу: "Параллелизм Java на практике", чтобы лучше понять, как работает параллелизм java. В главе 3, разделе 3.1: Видимость, есть пример, в котором книга пытается показать, как возникают проблемы с видимостью. Вот пример кода (листинг 3.1 в книге):


public class NoVisibility {
    private static boolean ready;
    private static int number;

    private static class ReaderThread extends Thread {
        public void run() {
            while (!ready)
                Thread.yield();
            System.out.println(number);
        }
    }

    public static void main(String[] args) {
        new ReaderThread().start();
        number = 42;
        ready = true;
    }
}

В книге говорится, что NoVisibility может зацикливаться вечно, потому что значение ready может никогда не стать видимым для потока чтения. Как это возможно? Мое общее понимание состоит в том, что ready в любом случае станет истинным в определенное время. Но я не могу понять, почему этого может не произойти, и цикл продолжается вечно. Может ли кто-нибудь помочь мне понять это лучше.


person Hossein    schedule 10.03.2013    source источник
comment
Кстати, это первый вопрос в разделе «Связанные». Вы искали, прежде чем опубликовать это?   -  person Burkhard    schedule 10.03.2013
comment
видимо, вы не знаете, для чего нужен -1. вы можете проголосовать за близкое. но -1 за действительный вопрос нечестно.   -  person Hossein    schedule 10.03.2013
comment
Тем более, что вопрос в той ссылке не совсем ясен. естественно, вы идете на чтение осмысленных вопросов. не очень общие. до сих пор не понимаю -1.   -  person Hossein    schedule 10.03.2013
comment
@Hossein Во всплывающей подсказке над -1 упоминается отсутствие исследований как возможная мотивация против. Не нажимая на ссылки, ТАК в основном сталкивает вас с лица, поскольку вы автор, ваш вопрос будет учитываться. (Не голосующий, просто это вероятное объяснение.)   -  person millimoose    schedule 10.03.2013
comment
@Hossein: чем полезен вопрос, если он почти дословно совпадает с уже заданным вопросом? Показывает ли это исследовательские усилия?   -  person Burkhard    schedule 10.03.2013


Ответы (1)


Потому что ready не помечен как volatile и значение может кэшироваться в начале цикла while, поскольку оно не изменяется в цикле while. Это один из способов оптимизации кода с помощью джиттера.

Таким образом, возможно, что поток запускается до ready = true и читает ready = false, кэширует этот поток локально и никогда больше не читает его.

Проверьте ключевое слово volatile.

Источник

person Burkhard    schedule 10.03.2013
comment
Буркхард, у меня есть вопрос к вам после просмотра различных ответов, данных по ссылке, которую вы разместили. Всегда ли поток кэширует переменную экземпляра для оптимизации производительности (или ее не определенного поведения)? Еще одна вещь, о которой мы говорим здесь, связана с кодом время исполнения. Верно? - person M Sach; 10.03.2013
comment
@MSach: возможно, он будет кэширован, но может и не кэшироваться (это зависит от JVM). Единственный способ убедиться в этом — объявить его изменчивым. Я не уверен, что понял ваш второй вопрос. Какие еще спектакли? - person Burkhard; 10.03.2013