Последовательность сигнализации потока

java multithreading

37 просмотра

2 ответа

В приведенном ниже коде я реализовал взаимодействие между потоками с помощью wait () -notify (), и это дает ожидаемый результат. Ожидаемый результат: 123456789 Фактический результат: 123456789

Мой вопрос заключается в том, есть ли какая-либо гарантия того, что «Главный поток» всегда получит первый шанс выполнения, поскольку планирование потоков зависит от jvm. И если «дочерний поток» получает первый шанс, сигнал notify () будет пропущен, а «главный поток» будет ждать вечно. Как я могу подтвердить, что «Основной поток» будет выполняться первым всегда. Также, пожалуйста, подтвердите, если приведенный ниже код может быть улучшен.

package com.test.Thread;

public class ThreadExample1 {

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

        ThreadChild1 lockingObj = new ThreadChild1();
        lockingObj .start();
        synchronized(lockingObj ){
            for(int i=1;i<10;i++){
                System.out.println("Main "+i);
            }
            lockingObj.wait();
            System.out.println("Main got notified");

        }

    }

}

class ThreadChild1 extends Thread{

    public void run(){
        synchronized(this){
            for(int i=1;i<10;i++){
                System.out.println("Child "+i);
            }
            this.notify();
            }
    }
}
Автор: RoyalTiger Источник Размещён: 08.11.2019 11:16

Ответы (2)


3 плюса

Решение

Ваш код неверен по той причине, что вы упомянули себя: вы не можете быть уверены, какой поток идет первым. Есть и другие вещи, которые могут пойти не так - waitможно проснуться без notify.

Вы можете прочитать об этом в Javadoc для waitметода , который также объясняет, что вы должны делать:

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

synchronized (obj) {
     while (<condition does not hold>)
         obj.wait();
     ... // Perform action appropriate to condition
 }

В своем коде вы можете решить его с помощью логической переменной, которая выражает условие «я был уведомлен»:

public class ThreadExample1 {

    public static void main(String[] args) throws InterruptedException {
        ThreadChild1 lockingObj = new ThreadChild1();
        lockingObj.start();

        synchronized (lockingObj) {
            for(int i = 1; i < 10; i++) {
                System.out.println("Main " + i);
            }
            while (!lockingObj.haveNotified) {
                lockingObj.wait();
            }
            System.out.println("Main got notified");
        }

    }

}

class ThreadChild1 extends Thread{
    private boolean haveNotified;
    public void run(){
        synchronized (this) {
            for (int i = 1; i < 10; i++) {
                System.out.println("Child " + i);
            }
            haveNotified = true;
            this.notify();
        }
    }
}
Автор: Erwin Bolwidt Размещён: 20.08.2016 12:56

1 плюс

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

Хорошая уловка для тестирования вашего кода - это приостановить / приостановить потоки в критические моменты, либо добавив точку останова в вашей IDE, добавив очень трудоемкую задачу / вызов, если это возможно (не отказоустойчиво), либо физически приостановив поток (не всегда идеальный вариант). ). Кроме того, я уверен, что есть библиотеки, чтобы расширить этот тип тестирования.

Я надеюсь, что это поможет вам немного в правильном направлении.

Автор: n247s Размещён: 20.08.2016 01:09
Вопросы из категории :
32x32