Значение использования ключевого слова, синхронизированного в следующем коде - PullRequest
0 голосов
/ 05 августа 2020

Я читал multi threading в Java из книги Java The Complete Reference by Herbert Schildt . Я наткнулся на следующий код [Стр. 252, 7-е изд.] , в котором объясняется использование потоков от wait() и notify() до suspend и resume в современных Java. Мой вопрос касается значения ключевого слова synchronization в двух местах в следующем коде (в run() методе класса NewThread):

// Suspending and resuming a thread the modern way.
class NewThread implements Runnable {
    String name;
    Thread t;
    boolean suspendFlag;
    NewThread(String threadname) {
        name = threadname;
        t = new Thread(this, name);
        suspendFlag = false;
        t.start();
    }
// This is the entry point for thread.
    public void run() {
        try {
            for (int i = 15; i > 0; i--) {
                System.out.println(name + ": " + i);
                Thread.sleep(200);
                synchronized (this) { //First doubt here
                    while (suspendFlag) {
                        wait();
                    }
                }
            }
        } catch (InterruptedException e) {
            System.out.println(name + " interrupted.");
        }
        System.out.println(name + " exiting.");
    }
    void mysuspend() {
        suspendFlag = true;
    }
    synchronized void myresume() { //Second doubt here
        suspendFlag = false;
        notify();
    }
}

class SuspendResume {
    public static void main(String args[]) {
        NewThread ob1 = new NewThread("One");
        NewThread ob2 = new NewThread("Two");
        try {
            Thread.sleep(1000);
            ob1.mysuspend();
            Thread.sleep(1000);
            ob1.myresume();
            ob2.mysuspend();
            Thread.sleep(1000);
            ob2.myresume();
        } catch (InterruptedException e) {
            System.out.println("Main thread Interrupted");
        }
        //some code
}

Мое сомнение здесь : Я знаю об использовании ключевого слова synchronization, т.е. разрешении только одному потоку вводить синхронизированный метод для одного и того же объекта, но здесь у нас есть два потока, работающих на двух разных объектах. Итак, каково значение обоих ключевых слов synchronization, используемых в приведенном выше коде.

Я попытался запустить приведенный выше код, удалив ключевое слово synchronized в каждом месте по-разному и одновременно. Я получаю ту же ошибку: java.lang.IllegalMonitorStateException: current thread is not owner разное количество раз и с разными номерами строк в зависимости от того, удаляю ли я оба или только одно (и какое) synchronization ключевое слово. Я поискал указанную выше ошибку и нашел ей объяснение здесь , но так и не смог связать ответ с моими сомнениями.

1 Ответ

0 голосов
/ 05 августа 2020

Проблема, которую решает synchronized, заключается в том, что он позволяет двум потокам иметь согласованное представление об общей переменной suspendFlag.

В некоторых реальных программах поток может установить другие общие переменные перед установкой susependFlag=false. Если synchronized не использовался, то ожидающий поток мог бы проснуться и увидеть suspendFlag==false, но не увидеть другие установленные переменные. Или, что еще хуже, он может видеть, что некоторые из них установлены, но не другие.

Без синхронизации Java не гарантирует, что разные потоки увидят переменные, обновляемые в одном порядке.

Я получаю ту же ошибку: java .lang.IllegalMonitorStateException: текущий поток не является владельцем.

Библиотека Java пытается помочь вам, заставляя вас использовать synchronized до того, как это позволит вам использовать wait() и notify(). Правило простое: вы можете вызывать o.wait(), o.notify() или o.notifyAll() только из кода, который находится внутри блока synchronized(o). Если вы нарушите это правило, библиотека выдаст исключение.

Когда ваш код вызывает o.wait() вызов wait () временно разблокирует блокировку монитора, чтобы другой поток мог для синхронизации на o и звоните o.notify(). Вызов o.wait() гарантированно повторно заблокирует o перед возвратом.

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