Java:为什么在这个有两个线程的简单示例中没有发生死锁

Java: why doesn't deadlock happen when in this simple example with two threads

我有这个代码:

public class UsbDrive extends HardDrive {
    private Date lastUpdate;

    private void updateDate()  {
        lastUpdate = new Date();
    }

    public synchronized void cutAndPaste(UsbDrive other, int originAddress, int destAddress)  {
        byte[] data = read(originAddress);

        boolean success = other.write(data, destAddress);
        if (success) {
            erase(originAddress);
            updateDate();
        } else {
            throw new RuntimeException("Write failed!");
        }
    }
}
class HardDrive  {
...
public synchronized byte[] read(int address)  {...}
public synchronized boolean write(byte[] data, int address)  {...}
    public synchronized void erase(int address)  {...}
...

我正在尝试模拟死锁

public class Main  {
 private static UsbDrive usb1 = new UsbDrive();
    private static UsbDrive usb2 = new UsbDrive();

    public static void main(String[] args) throws  Exception  {
        Thread thread1 = new Thread(new ThreadA());
        Thread thread2 = new Thread(new ThreadB());

        thread1.start();
        thread2.start();

        thread1.join();
        thread2.join();
    }

    static class ThreadA implements Runnable  {
        @Override
        public void run()  {
            try  {
                Thread.sleep(5000);
            }
            catch (Exception e)  {
                e.printStackTrace();
            }
            synchronized (usb1) {
                usb1.cutAndPaste(usb2, 1, 2);
            }
        }
    }

    static class ThreadB implements Runnable  {
        @Override
        public void run()  {
            synchronized (usb2) {
                usb2.cutAndPaste(usb1, 1, 2);
            }
        }
    }
}

但是并没有发生死锁 - 为什么? ThreadA 调用锁定在 usb1 上的方法 cutAndPaste(),而在内部调用锁定在 usb2 上的方法 write() 不应该发生死锁吗? 我应该如何更改代码以触发死锁?

我得到这个输出:

reading data
Erasing data
reading data
Erasing data

据我所知,这是一个决定死锁是否发生的竞争条件,使死锁更有可能发生的一个好选择是循环,但更简单的选择可能是插入 Thread.sleep(5000);byte[] data = read(originAddress);boolean success = other.write(data, destAddress); 之间 UsbDrive::cutAndPaste编辑: 并删除现有的 Thread.sleep(5000);

编辑: 澄清答案。

EDIT2: 我只是 运行 修改过的代码,现在确实导致了死锁:


import java.util.Date;

public class Main  {
 private static UsbDrive usb1 = new UsbDrive();
    private static UsbDrive usb2 = new UsbDrive();

    public static void main(String[] args) throws  Exception  {
        Thread thread1 = new Thread(new ThreadA());
        Thread thread2 = new Thread(new ThreadB());

        thread1.start();
        thread2.start();

        thread1.join();
        thread2.join();
    }

    static class ThreadA implements Runnable  {
        @Override
        public void run()  {
            synchronized (usb1) {
                usb1.cutAndPaste(usb2, 1, 2);
            }
        }
    }

    static class ThreadB implements Runnable  {
        @Override
        public void run()  {
            synchronized (usb2) {
                usb2.cutAndPaste(usb1, 1, 2);
            }
        }
    }
}

class UsbDrive extends HardDrive {
    private Date lastUpdate;

    private void updateDate()  {
        lastUpdate = new Date();
    }

    public synchronized void cutAndPaste(UsbDrive other, int originAddress, int destAddress)  {
        byte[] data = read(originAddress);

        try  {
            Thread.sleep(5000);
        }
        catch (Exception e)  {
            e.printStackTrace();
        }

        boolean success = other.write(data, destAddress);
        if (success) {
            erase(originAddress);
            updateDate();
        } else {
            throw new RuntimeException("Write failed!");
        }
    }
}

class HardDrive  {
    public synchronized byte[] read(int address)  {return new byte[]{};}
    public synchronized boolean write(byte[] data, int address)  {return true;}
    public synchronized void erase(int address)  {}
}