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

Java deadlock, 2 threads seems to be blocking each other

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

代码是这样的:

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();
        }
    }
}

Customer.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。第二个线程似乎根本 运行。它不会检索包或插入包,也不会释放锁。任何关于如何解决此问题的 help/advice 都将受到赞赏,如果有人有好的设计模式提示,我会更乐意学习。

顺便说一句,程序基本上模拟了一个盒子,一次可以装 1 个包裹,如果满了顾客拉包裹,如果空了商店将放入 1 个包裹。

编辑:

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

您正在单个线程中调用 Shop 和 Customer 的 运行() 方法,而没有创建线程。

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

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

为他们开启新话题

或者你可以扩展 Thread 而不是实现 运行nable(它实现了 运行nable)并像你​​一样覆盖 运行 方法并调用它们的 start() 方法直接。