Как работает join ()?(Многопоточность в Java) - PullRequest
12 голосов
/ 04 февраля 2011

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

Вопрос

(множественный выбор): каковы некоторые из возможных результатов для программы ниже?

A) Значение 1. Значение 1. Конечное значение 1.

В) Значение 1. Значение 1. Конечное значение 2.

С) Значение 1. Конечное значение равно 1. Значение равно 2.

D) Значение 1. Конечное значение 2. Значение 2.

Программа

public class Thread2 extends Thread {

    static int value = 0;
    static Object mySyncObject = new Object();

    void increment() {

        int tmp = value + 1;
        value = tmp;

    }

    public void run() {

        synchronized(mySyncObject) {

            increment();
            System.out.print("Value is " + value);

        }

    }

    public static void main(String[] args) throws InterruptedException {

        Thread t1 = new Thread2();
        Thread t2 = new Thread2();

        t1.start();
        t2.start();

        t1.join();
        t2.join();

        System.out.print("Final value is " + value);

    }

}

Правильные ответы: A), C) и D).

Для случая А) Я не понимаю, как возможно, чтобы оба потока (после увеличения, казалось бы, статической переменной из синхронизированного блока (!)) В конечном итоге были установлены в 1, и, таким образом, конечное значение также равно 1. ..

Случаи C и D одинаково сбивают меня с толку, потому что я действительно не понимаю, как возможно, что main () завершает работу до того, как оба требуемых потока (t1 и t2) это делают. Я имею в виду, что их методы join () были вызваны из функции main, поэтому, насколько я понимаю, функция main должна ждать, пока оба t1 и t2 будут выполнены с их методом run () (и, таким образом, их значения будут напечатаны) ... ??

Было бы замечательно, если бы кто-нибудь мог мне помочь в этом.

Заранее спасибо, высоко ценится! васаби

Ответы [ 2 ]

24 голосов
/ 04 февраля 2011

Что-то не так с ответами или вопросом.

Ваше понимание join() верно.Сообщение «Final value is» не может быть напечатано, пока не завершатся оба потока.Вызовы join() гарантируют это.

Кроме того, метод increment() вызывается только из блока synchronized, связанного со статическим полем.Таким образом, этот метод не может быть вызван одновременно двумя потоками.Выход «Значение есть» также находится в том же синхронизированном блоке.Таким образом, нет доступа к свойству value из любой точки, кроме как в синхронизированном блоке.Поэтому эти операции являются поточно-ориентированными.

Единственный возможный вывод этой программы - «Значение равно 1. Значение равно 2. Окончательное значение равно 2».(На самом деле между выводами нет точек или пробелов - я просто сопоставляю формат ответов.)

Я не могу объяснить, почему это не соответствует ни одному из ответов, за исключением того, что тот, кто написал вопрос, что-то испортилдо.

0 голосов
/ 21 августа 2012

Сначала я хотел бы согласиться с Рлиби.Его ответ можно доказать, написав в программе подарок для учителя.Если мы опускаем этот взгляд на это:

гарантированно будет два отпечатка 'Value is ...' , невозможно напечатать 'Value is 1' дважды, поскольку приращение равносинхронизируется статическим объектом (это исключает A и B) , порядок операторов печати не может быть спрогнозирован , но: если мы читаем 'Окончательное значение равно x', то должно быть«Значение равно X», независимо от того, существует ли оно до или после, но оно должно существовать
...