繁体   English   中英

在 java 中使用线程的死锁情况?

[英]Deadlock situation using threads in java?

我创建了 3 个类,

  1. class InCharge - 应检查当前余额,同时检查Client线程应wait() ,直到InCharge线程完成测试(15 秒)
  2. Class 客户端 - 应该每 5 秒取款,但是当InCharge线程运行时Client线程应该等到InCharge线程说Notify()
  3. class 银行 - 持有当前余额,以及Synchronized块的锁定。

根据我的调试,似乎是InCharge发送了Notify()但由于某种原因客户端没有收到通知,我猜问题是因为while(true) ,但我想不出解决方法.

你能帮忙找出问题吗?

主要的:

    public class Main {
    public static void main(String[] args) {
        Object obj = new Object();
        Bank bank = new Bank(100000);

        Client client1 = new Client(obj, bank);
        InCharge inCharge = new InCharge(obj, bank);

        client1.setName("client1");
        inCharge.setName("inCharge");

        client1.start();
        inCharge.start();
    }
}

银行:

public class Bank {
    private int balance;
    private boolean bankIsClose = false;
    public Bank(int balance) {
        this.balance = balance;
    }
    public int getBalance() {
        return balance;
    }

    public boolean isBankIsClose() {
        return bankIsClose;
    }

    public void setBankIsClose(boolean bankIsClose) {
        this.bankIsClose = bankIsClose;
    }

    public void setBalance(int balance) {
        this.balance = balance;
    }
    public synchronized void withdraw(String name, int amount){
        if (this.balance - amount >= 0) {
            this.balance = this.balance - amount;
            System.out.println(name+" "+this.balance + " withdrawed - " + amount);
        }
    }
}

客户:

public class Client extends Thread {
    private Object obj;
    private Bank bank;

    Client(Object obj, Bank bank) {
        this.obj = obj;
        this.bank = bank;
    }

    @Override
    public void run() {
        int randomNumber;
        while (bank.getBalance() > 0) {
            synchronized (obj) {
                randomNumber = ((int) (Math.random() * (5000 - 1000 + 1)) + 1000);
                if (!bank.isBankIsClose()) {
                    try {
                        obj.wait();
                        bank.withdraw(currentThread().getName(), randomNumber);
                    } catch (Exception e) {}
                }
            }
        }
    }
}

负责:

public class InCharge extends Thread {
    private Object obj;
    private Bank bank;

    InCharge(Object obj, Bank bank) {
        this.obj = obj;
        this.bank = bank;
    }

    @Override
    public void run() {
        while (true) {
            synchronized (obj) {
                bank.setBankIsClose(true);
                try {
                    System.out.println("Charge is here!, current balance is: " + bank.getBalance());
                    Thread.sleep(5000);
                } catch (InterruptedException e) {}
                bank.setBankIsClose(false);
                obj.notify();
            }
        }
    }
}

您的应用程序确实为我运行而无需更改,但由于银行开/闭环的性质,银行不是很友好。

银行关闭 5 秒,然后打开,但会立即尝试再次进入同步块以关闭银行。 有时 InCharge/bank 线程会击败客户端线程以访问synchronized(obj) 这是正常的,也是意料之中的,但这意味着在许多周期中,银行会继续休眠(5000),而上一个周期显示的余额相同,并且在这之间没有客户提款代码运行。

为了模拟银行的正常工作时间,您可以在 InCharge 线程中同步后添加第二个小 sleep(),此期间将显示客户端更频繁地获取锁以进行提款。 将 InCharge.run() 更改为:

public void run() {
    while (true) {
        synchronized (obj) {
            bank.setBankIsClose(true);
            try {
                System.out.println("Charge is here!, current balance is: " + bank.getBalance());
                Thread.sleep(5000);
            } catch (InterruptedException e) {}
            bank.setBankIsClose(false);
            System.out.println("Now the bank is open for business");
            obj.notify();
        }

        // Simulate a period of bank being open:
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {}
    }
}

如果您进一步开发应用程序,您应该尝试 2 个客户端线程,并且需要将notify()更改为notifyAll()以确保所有客户端都有机会使用银行。 还将您的代码更改为 Runnable 而不是扩展 Thread 将使代码更清晰。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM