0

我正在用 java 做一些练习(你们中的一些人可能会猜想代码是从哪里来的)。我尝试使用以下代码引发死锁情况:

class Resource {

    public Integer value = 42;
}

public class DeadLockRisk implements Runnable {

    private Resource resourceA = new Resource();
    private Resource resourceB = new Resource();

    public void write(int a, int b) {

        System.out.println(Thread.currentThread().getName() + " try write Lock A");

        synchronized(resourceA) {

            System.out.println(Thread.currentThread().getName() + " write Lock A");
            System.out.println(Thread.currentThread().getName() + " try write Lock B");

            synchronized(resourceB) {

                System.out.println(Thread.currentThread().getName() + " write Lock B");

                resourceA.value = a;
                resourceB.value = b;
        //sit on it!
        //try { Thread.sleep(5000); } catch (Exception e) {}

        System.out.println(Thread.currentThread().getName() + " release write B");
        }
        System.out.println(Thread.currentThread().getName() + " release write A");
    }
    }

    public int read() {

    Integer retVal;
        System.out.println(Thread.currentThread().getName() + " try read Lock B");

        synchronized(resourceB) {

            System.out.println(Thread.currentThread().getName() + " read Lock B");
            System.out.println(Thread.currentThread().getName() + " try read Lock A");

            synchronized(resourceA) {

                System.out.println(Thread.currentThread().getName() + " read Lock A");
                retVal = resourceB.value + resourceA.value;
        System.out.println(Thread.currentThread().getName() + " release read A");
            }
        System.out.println(Thread.currentThread().getName() + " release read B");
        }
    return retVal;
    }

    public void run() {


    if (Thread.currentThread().getName().equals("Thread-1")) {
        write(1,2);
    }

    System.out.println(read());
    }

    public static void main(String[] args) {

        Thread ta = new Thread(new DeadLockRisk());
        Thread tb = new Thread(new DeadLockRisk());
        ta.start(); tb.start();
    }
}

(javac -version javac 1.6.0_0 uname -a Linux inspiron 2.6.29 #1 SMP Sat May 16 10:56:17 CEST 2009 i686 GNU/Linux)

并获得(在其他情况下)以下输出:

Thread-1 尝试写入 Lock A
Thread-0 尝试读取 Lock B
Thread-1 写锁 A <=====
Thread-0 读取锁 B
Thread-1 尝试写 Lock B
Thread-0 尝试读取 Lock A
Thread-1 写锁 B
Thread-0 读取锁 A <=====
Thread-1 释放写入 B
Thread-0 发布读取 A
Thread-1 释放写入 A
Thread-0 释放读取 B
Thread-1 尝试读取 Lock B
154
Thread-1 读取锁 B
Thread-1 尝试读取 Lock A
Thread-1 读取锁 A
Thread-1 发布读取 A
Thread-1 发布读取 B
3

我看错了什么?在 Thread-1 释放锁之前,Thread-0 怎么能在 read() 中进入临界区并获得 A 上的锁。这可能是因为输出不同步吗?此代码永远不会发生死锁。

4

2 回答 2

5

您将不同的 DeadLockRisk 实例传递给两个线程,因此它们不会在同一个对象上同步。

于 2009-07-19T16:12:41.363 回答
1

两个 DeadlockRisk 实例对于 resourceA 和 resourceB 字段都有不同的实例。如果您希望代码按预期执行,请将实例字段更改为静态字段。

于 2009-07-19T16:15:03.107 回答