Почему операторы после оператора if не работают должным образом в синхронизированном методе - PullRequest
2 голосов
/ 14 февраля 2020

У меня есть простой класс с двумя синхронизированными методами. Тот, который должен снять около sh, и тот, который должен положить около sh.

И тогда у меня есть другой основной класс с внутренним классом. И основной класс, и внутренний класс реализуют Runnable, где основной класс использует метод «изъятия», а внутренний класс - метод «депозита».

Когда это будет сделано, я создаю два потока для запуска (т. Е. Запуска) отдельных методов в отдельных классах "Runnable".

Класс с синхронизированными методами имеет следующие методы:

package test;

public class ThreadClass {


int amount = 10;


synchronized void withdraw(int amount) {
    System.out.println("going to withdraw...");

    if(this.amount < amount) {
        System.out.println("Less balance..");
        try {
            wait();

        }
        catch(Exception e) {
            e.printStackTrace();
        }

    }
    this.amount+=amount;
    System.out.println("withdrawal completed");
}


synchronized void deposit(int amount) {
    System.out.println("going to deposit...");
    this.amount+=amount;
    System.out.println("deposit completed");
    notify();       
 }
}

и класс, который отвечает за реализацию Runnable, а также за запуск примера приложения, выглядит следующим образом:

package test;

public class ThreadTest implements Runnable {

@Override
public void run() {

    ThreadClass withDraw = new ThreadClass();
    withDraw.withdraw(20);


}



class Threadtest2 implements Runnable{

@Override
public void run() {
    ThreadClass t10 = new ThreadClass();
    t10.deposit(60);

 }

}

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

    ThreadTest tester = new ThreadTest();
    ThreadTest.Threadtest2 tester2 = tester.new Threadtest2();


    Thread t1 = new Thread(tester);
    t1.start();

    Thread t2 = new Thread(tester2);
    t2.start();





 }

}

Поэтому, когда я запускаю эту программу, я ожидаю, что notify () -call в методе deposit должен уведомить методdraw () - так, чтобы последние строки также выполнялись, т.е.

    this.amount+=amount;
    System.out.println("withdrawal completed");

.. но приложение продолжало работать и никогда не доходило до этой строки вручную прекратить его. Разве это не правильный способ сделать это?

1 Ответ

3 голосов
/ 14 февраля 2020

Методы synchronized синхронизируются на текущем экземпляре объекта. Так что wait() и notify() должны быть вызваны для одного и того же объекта. Но вы создаете два разных экземпляра объекта ThreadClass, поэтому вы вызываете wait() и notify() для разных объектов.

Вы должны создать один экземпляр ThreadClass и передать его потокам, например, через конструктор:

public class ThreadTest implements Runnable {

    private ThreadClass account;

    public ThreadTest(ThreadClass account) {
        this.account = account;
    }

    @Override
    public void run() {
        account.withdraw(20);
    }

}

class Threadtest2 implements Runnable{

    private ThreadClass account;

    public Threadtest2(ThreadClass account) {
        this.account = account;
    }

    @Override
    public void run() {
        account.deposit(60);
    }

}

И затем инициализировать их следующим образом:

ThreadClass account = new ThreadClass();

ThreadTest tester = new ThreadTest(account);
ThreadTest.Threadtest2 tester2 = tester.new Threadtest2(account);

Также обратите внимание, что после wait() условие this.amount < amount все еще может быть истинным, если депозит сумма была недостаточной. Таким образом, вы должны проверить сумму и позвонить wait() в цикле, пока это условие не будет выполнено.

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