Странное поведение в Java с несинхронизированным доступом в многопоточной программе - PullRequest
5 голосов
/ 05 января 2012

Я изменяю значение, которое используется, чтобы определить, когда цикл while завершается в отдельном потоке.
Я не хочу знать, как заставить это работать. Если я получаю доступ к проверке переменных только через синхронизированные методы получения / установки, она работает как положено ..

Я бы ожидал, если некоторые команды чтения / записи будут потеряны из-за параллелизма, программа иногда не завершает работу, но никогда не завершает. Вот что меня смущает ..
Я хотел бы знать, почему программа никогда не завершается без команды print. И я хотел бы понять, почему команда print что-либо меняет ..

     

    public class CustomComboBoxDemo  {
        public static boolean test = true;
        public static void main(String[] args) {
            Thread user =new Thread(){
                @Override
                public void run(){
                    try {
                        sleep(2000);
                    } catch (InterruptedException e) {}
                    test=false;
                }
            };
            user.start();
            while(test) {
                System.out.println("foo"); //Without this line the program does not terminate..
            }
        }
    }

Ответы [ 6 ]

8 голосов
/ 05 января 2012

Наиболее вероятное объяснение состоит в том, что переменная читается только один раз , превращая while в бесконечный цикл (или не-операцию).Поскольку вы не объявили test как volatile, компилятору разрешено выполнять такую ​​оптимизацию.

Как только вы вызываете внешнюю функцию из цикла, компилятор больше не может доказать, что test остается неизменным на протяжении итераций цикла и не выполняет оптимизацию.

1 голос
/ 05 января 2012

Если переменная test не определена как volatile, компилятор, вероятно, оптимизирует цикл, не содержащий операций, в цикл while(true) для основного потока, и программа никогда не завершится.

В противном случае значение переменной test фактически проверяется, и когда ваш второй поток меняет свое значение, основной поток выходит из цикла while и ваша программа завершается.

0 голосов
/ 05 января 2012

Я не понимаю, что вы пытаетесь сделать, используя код, который, как вы знаете, неправильно синхронизирован.

Как уже сообщали некоторые, код на их машине ведет себя иначе, чем на вашей машине.Поведение плохо синхронизированного кода: undefined .Нет смысла пытаться понять, что он делает, так как это поведение будет меняться в зависимости от версии или архитектуры JVM.

0 голосов
/ 05 января 2012
public static boolean test = true;
public static void main(String[] args) {
    Thread user =new Thread(){
        @Override
        public void run(){
            try {
                sleep(2000);
            } catch (InterruptedException e) {}
            test=false;
            System.out.println("Thread.end <"+test+">");
        }
    };
    user.start();
    while(test);
}

Это интересно. Компилятор, скорее всего, оптимизирует это, находясь в бесконечном цикле, не считывая значение в каждом цикле.

Определение теста как volatile исправляет это и позволяет вашей программе завершаться

Кстати: вы, вероятно, уже знаете, что должны использовать user.join (), чтобы дождаться окончания потока

0 голосов
/ 05 января 2012

Похоже, ваш цикл неправильно компилируется в ожидание занятости.Добавление изменяемого ключевого слова к вашему логическому значению исправляет проблему.

0 голосов
/ 05 января 2012

Полагаю, это как-то связано со способом обработки ввода-вывода. Без печати вы, вероятно, увидите приложение Java, использующее все доступное время процессора; с печатью вполне вероятно, что задержки ввода-вывода дают достаточно процессорного времени для другой обработки.

Быстрый способ проверить эту теорию состоит в том, чтобы поместить printlns в метод run () вашего потока, чтобы увидеть, выполняется ли этот поток на самом деле. По моему опыту, бесконечные пустые циклы вызывают много странного поведения.

Тем не менее, похоже, что на моей рабочей станции в JDK 1.6.0_10_b23

все нормально
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...