Java:为什么在这个简单的例子中,当有两个线程时,死锁不会发生?

问题描述 投票:0回答:1

我有这段代码。

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

然而死锁并没有发生--为什么?线程A调用方法 cutAndPaste() 锁定 usb1而在该方法中 write() 被称为锁定在 usb2不应该出现死锁吗?我应该如何修改代码来触发死锁?

我得到这样的输出。

reading data
Erasing data
reading data
Erasing data
java multithreading concurrency deadlock
1个回答
1
投票

就我所见,决定死锁是否发生的是一个竞赛条件,一个让死锁更有可能发生的好方案是循环,但一个更简单的方案可能是插入 Thread.sleep(5000); 之间 byte[] data = read(originAddress);boolean success = other.write(data, destAddress);UsbDrive::cutAndPaste. EDIT: 并删除现有的 Thread.sleep(5000);.

EDIT: 澄清的答案。

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)  {}
}
© www.soinside.com 2019 - 2024. All rights reserved.