Программа останавливается: wait () и notify()


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

Для достижения этой цели я использую синхронизированный блок вместе с wait() и notify().

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

Вот код:

--> это используемый объект, который будет передан синхронизированному блоку.

package com.vipin.multithread.variousdemos;

    public class SyncObject {

        public SyncObject () {  

        }
}

Нечетная Нить:

package com.vipin.multithread.variousdemos;

public class OddThread implements Runnable {

private Thread t;
int index=0;
SyncObject so=null;

int odd_nums[] = {1,3,5,7,9};

public OddThread(SyncObject so) {
    t = new Thread(this,"Odd Thread");
    this.so = so;
    t.start();
}

public Thread getThreadInstance() {
    return t;
}

@Override
public void run() {
    while (true) {
        synchronized(so) {
            System.out.println("Odd num is --->" + odd_nums[index]);
            try {
                so.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            index++;
            so.notify();
            if(index>=5) {
                return;
            }
        }
    }
}
}

Четный поток: обновление

package com.vipin.multithread.variousdemos;

public class EvenThread implements Runnable {

private Thread t;
int index=0;
SyncObject so=null;

int even_nums[] = {2,4,6,8,10};

public EvenThread(SyncObject so) {
    t = new Thread(this, "Even thread");
    this.so = so;
    t.start();
}

public Thread getThreadInstance() {
    return t;
}

@Override
public void run() {
    while(true) {   
        synchronized(so) {
            System.out.println("Even num is --->" + even_nums[index]);
            so.notify(); <-- Here we are notifying.
            try {
                so.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            index++;
            //so.notify(); <-- commented out.
            if(index>=5) {
                break;
            }
        }
    }
}
}

Основное Применение:

package com.vipin.multithread.variousdemos;

public class EvenOddDemo {

public static void main(String[] args) throws InterruptedException {
    SyncObject so = new SyncObject();

    OddThread ot = new OddThread(so);
    EvenThread et = new EvenThread(so);

    System.out.println("nIn main thread");

    Thread.sleep(1000000000);

    System.out.println("Exiting main thread...");
}
}
Как видно из кода, я создаю два потока для печати четных и нечетных чисел. Я использую синхронизированный блок и передаю объект типа = = > SyncObject.

SyncObject я передаю в качестве аргумента этим различным потокам в main.

Однако эта программа останавливается, т. е. выполняется только первый оператор, и затем он ждет вечно:

Вот результат:

Нечетное число - - - >1

В главном потоке Четное число - - - >2

Я не могу понять, почему эта программа ждет вечно, я использую тот же объект, на который мы вызываем synchronized (), wait () и notify (). Как я понимаю, это должно сработать, не знаю, почему это не работает.

Любые подсказки о том, почему это ждет вечно.

Обновление:

Я сделал некоторые изменения в коде, обновил и его работать отлично.

У меня все еще есть некоторые сомнения. Вызывает ли поток notify (), даже если он не заблокировал монитор, как в моем случае после обновления кода.

Последовательность событий:

Нечетный поток сначала выполняется, затем он вызывает wait ()

Даже поток работает, печатает msg и вызывает notify ()

Когда даже поток вызывает notify(), в этот момент у него есть монитор, поэтому, когда он вызывает notify (), все еще владеет монитором?

Теперь, после того как четный поток вызывает notify (), нечетный поток получает уведомление, и, следовательно, он начинает выполнение с точки, в которой он спал. Он выполняет некоторое выполнение и вызывает notify (), в этот момент я предполагаю, что нечетный поток не владеет монитором, он вызывает notify (). Итак, мой вопрос заключается в том, работает ли функция notify() одинаково независимо от того, принадлежит ли поток монитору?

Только когда человек делает код, он действительно понимает это. Я читал книга и я чувствовали, что я все понял,и, кажется, я вернулся к началу!
1 2

1 ответ:

Проблема здесь просто в том, что оба потока идут прямо в ожидание. Поток 1 получает so, выводит значение и ждет. Затем поток 2 получает so, выводит значение и ждет. Так что оба спят, потому что некому их предупредить. Итак, простое исправление состояло бы в том, чтобы сделать so.notify(), прямо перед so.wait(). Тогда они не будут бесконечно ждать.

EDIT

Нечетный поток запускается, выполняется и затем ожидает. Тогда даже поток запускается, выполняет, уведомляет и затем ждет. Даже поток удерживает блокировку над монитором, пока он не перейдет в режим ожидания.

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

Если четный поток не вызывал notify, то нечетный поток будет продолжать спать. Четная нить пошла бы ждать и отпустила замок. Ни один поток не опрашивает и не пытается получить блокировку, поэтому программа остается в подвешенном состоянии. государство.

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