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) {}
}
我有这个代码:
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) {}
}