我对Java在资源分配方面的同步工作方式感到困惑。 当我在Java中使用以下代码时:
import java.util.concurrent.Semaphore;
public class Deadlock {
public Deadlock () {
Semaphore mutex[] = new Semaphore[4];
for (int i = 0; i < 4; i++)
mutex[i] = new Semaphore(1);
A threadA = new A(mutex);
B threadB = new B(mutex);
C threadC = new C(mutex);
threadA.start();
threadB.start();
threadC.start();
}
private class A extends Thread {
private Semaphore[] resource;
public A(Semaphore[] m) {
resource = m;
}
public void run() {
System.out.println("A started");
synchronized( resouce[1] ) {
System.out.println("A locks rsc 1");
synchronized (resource[0]) {
System.out.println("A locks rsc 0");
}
}
System.out.println("A finished");
}
}
private class B extends Thread {
private Semaphore[] resource;
public B(Semaphore[] m) {
resource = m;
}
public void run() {
System.out.println("B started");
synchronized( resouce[3] ) {
System.out.println("B locks rsc 3");
synchronized (resource[0]) {
System.out.println("B locks rsc 0");
synchronized (resource[2]) {
System.out.println("B locks rsc 2");
}
}
}
System.out.println("B finished");
}
}
private class C extends Thread {
private Semaphore[] resource;
public C(Semaphore[] m) {
resource = m;
}
public void run() {
System.out.println("C started");
synchronized( resouce[2] ) {
System.out.println("C locks rsc 2");
synchronized (resource[1]) {
System.out.println("C locks rsc 1");
}
}
System.out.println("C finished");
}
}
}
据我了解,当线程A启动时,线程A锁定资源1和资源0。 因此,当线程B启动时,它将获取资源3的锁定,但是将等待资源0从线程A释放。由于线程B没有锁定资源0,它将无法等待资源2。 当线程C启动时,它将锁定资源2,但也等待资源1从线程A释放。
此处,从P到R的节点是指请求资源的进程。从R到P的节点意味着进程已锁定资源。
我是否理解正确? 欢迎任何帮助。 谢谢。
答案 0 :(得分:0)
当线程B启动时,它将获取资源3的锁定,但是将等待资源0从线程A释放
啊,但是假设A
仍然在运行。它可能已经完成,或者甚至可能尚未开始。您遇到死锁情况的可能性可能只发生在1000次运行中的1次。这是它们同时异步运行的线程的本质。很难预测它们的确切行为。
此外,通过调用正在执行同步的System.out.println(...)
,您也会使事情变得复杂。这会引发您的测试并改变比赛条件。
我是否正确理解了这一点?
我认为您正确理解资源图,而不是在正确的时间达到完美的死锁点有多难。
尝试的一件事是在while(true)
循环中执行以下操作。
while (true) {
A threadA = new A(mutex);
B threadB = new B(mutex);
C threadC = new C(mutex);
threadA.start();
threadB.start();
threadC.start();
threadA.join();
threadB.join();
threadC.join();
}
在某些时候输出将停止并且CPU将变为0并且您将知道它已经达到死锁。