为什么if语句后的语句在同步方法中未按预期运行

时间:2020-02-14 15:16:59

标签: java multithreading concurrency synchronization

我有一个带有两个同步方法的简单类。一种应提取现金,另一种应存款。

然后我有另一个带有内部类的主类。主类和内部类都实现了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();





 }

}

因此,当我运行该程序时,我期望deposit方法中的notify()调用应通知withdraw()方法,以便最后一行也得到执行,即

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

..但是应用程序一直在运行,并且从未到达该行,因此我必须手动终止它。这不是正确的方法吗?

1 个答案:

答案 0 :(得分:3)

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(),直到满足此条件为止。