Java死锁,2个线程似乎互相阻塞

标签 java multithreading deadlock

在尝试运行两个相互依赖的线程时,我似乎遇到了有关死锁的问题。

代码是这样的:

Box.Java(主要)

package exe4;

public class Box {

    private static boolean boxStatus;
    static Thread boxThread = Thread.currentThread();

    public Box(){
        Box.boxStatus = true;
    }

    public static void main(String[] args) throws InterruptedException{
        Box box = new Box();
        Shop shop = new Shop(box, "Post Office");
        Customer customer = new Customer(box, "Daniel Netzer");

        shop.run();
        customer.run();

        Thread.sleep(60000);
    }

    public boolean isBoxStatus() {
        return boxStatus;
    }

    public void setBoxStatus(boolean boxStatus) {
        Box.boxStatus = boxStatus;
    }

}

Shop.java

package exe4;

public class Shop implements Runnable{

    private static Box box;
    private static String name;
    private static Object shopLock = new Object();

    public Shop(Box box, String name){
        Shop.box = box;
        Shop.name = name;
    }

    public static Object getShopLockMonitor(){
        return Shop.shopLock;
    }

    public String getName() {
        return name;
    }

    public synchronized void setName(String name) {
        Shop.name = name;
    }

    public static Box getBox() {
        return box;
    }

    public synchronized void setBox(Box box) {
        Shop.box = box;
    }

    public synchronized void  depositBox(){
        Shop.box.setBoxStatus(true);
        synchronized(Customer.getCustomerLockMonitor()){
            Customer.getCustomerLockMonitor().notifyAll();}
    }

    public synchronized void  printDeposit(){
        System.out.println("New package have been deposited into your box.");
    }

    @Override
    public void run() {
        while(Box.boxThread.isAlive()){
            while(box.isBoxStatus()){
                synchronized(Shop.getShopLockMonitor()){
                    try {
                        System.out.println("Box is full, waiting for customer withdrawal.");
                        Shop.getShopLockMonitor().wait();
                    } catch (InterruptedException e) {}
                }
            }
            depositBox();
            printDeposit();
        }
    }
}

客户.java

package exe4;

public class Customer implements Runnable{

    private static Box box;
    private static String name;
    private static Object customerLock = new Object();

    public Customer(Box box, String name){
        Customer.box = box;
        Customer.name = name;
    }

    public static Object getCustomerLockMonitor(){
        return Customer.customerLock;
    }

    public String getName() {
        return name;
    }

    public synchronized void setName(String name) {
        Customer.name = name;
    }

    public static Box getBox() {
        return box;
    }

    public synchronized void setBox(Box box) {
        Customer.box = box;
    }

    public synchronized void  withdrawBox(){
        Customer.box.setBoxStatus(false);
        synchronized(Shop.getShopLockMonitor()){
            Shop.getShopLockMonitor().notifyAll();}
    }

    public synchronized void  printWithdraw(){
        System.out.println("Package have been withdrawed from box.");
    }

    @Override
    public void run() {
        while(Box.boxThread.isAlive()){
            while(!box.isBoxStatus()){
                synchronized(Customer.getCustomerLockMonitor()){
                    try {
                        System.out.println("Box is empty, waiting for a new package to arrive.");
                        Customer.getCustomerLockMonitor().wait();
                    } catch (InterruptedException e) {}
                }
            }
            withdrawBox();
            printWithdraw();
        }

    }
}

我没有从控制台收到任何错误,但它只打印我首先运行的线程上的第一个 syso。第二个线程似乎根本没有运行。它不会检索包裹或插入包裹,也不会释放锁。任何有关如何解决此问题的帮助/建议都将受到赞赏,如果有人有好的设计模式技巧,我将非常乐意学习。

顺便说一句,该程序基本上模拟了一个盒子,它可以一次容纳 1 个包裹,如果满了,顾客就会拉出包裹,如果空了,商店就会放入 1 个包裹。

编辑:

它与建议的重复内容不同,因为在另一个问题中没有主线程的 java 代码,因此它不包含我自己问题的答案。

最佳答案

您在单个线程中调用 Shop 和 Customer 的 run() 方法,而不创建线程。

shop.run(); 替换为 new Thread(shop).start()

customer.run(); 替换为 new Thread(customer).start()

为他们启动新线程

或者你可以扩展Thread而不是实现Runnable(它无论如何都实现Runnable)并像你​​一样重写Run方法并直接调用它们的start()方法。

关于Java死锁,2个线程似乎互相阻塞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34475530/

相关文章:

java - 解析格式化日期在 Java 11 中给出 null,但在 Java 8 中给出正确的输出

python - 如何在python中运行在该线程外的线程中调用的函数

java - 使用 JVMTI 进行死锁检测

java - 为什么我的查询会死锁?

java - 使用waf构建Java项目

java - 在派生类中调用 super.equals() 同时重写 equals

java - 检测文档中的样式文本

c++ - 循环将执行分为几个线程(1-N-1-N-1…)

Java执行器在执行过程中无法添加新任务

mysql事务死锁