这段代码怎么会导致死锁?

时间:2012-12-11 15:21:32

标签: java scjp

在通过SCJP6考试模拟器时,我发现了这样的问题:

class Clerk implements Runnable {

    private Record A, B;

    public Clerk(Record a, Record b) {
        A = a;
        B = b;
    }

    public void run() {
        while(true) {
            doStuff(A, B);
        }
    }

    public synchronized void doStuff(Record a, Record b) {
        synchronized(a) {
        synchronized(b) {
            a.add(1);
            b.add(-1);
        }}
    }

}

然后

Record a = new Record();
Record b = new Record();

new Thread(new Clerk(a, b)).start();
new Thread(new Clerk(a, b)).start();

答案说这段代码可以导致死锁,但我不明白 - 这究竟是怎么可能的?有人可以帮我解决这个问题吗?

2 个答案:

答案 0 :(得分:9)

除了它不编译之外,该代码中没有死锁。这段代码肯定会造成死锁:

new Thread(new Clerk(a, b)).start();
new Thread(new Clerk(b, a)).start();

因此,如果问题是:Clerk类是否可能成为死锁的来源?然后答案是肯定的。

修改

应该快速死锁的简短示例。如果像原始问题一样使用a和b,程序运行正常。

public class Test1 {

    public static void main(String[] args) {
        Record a = new Record();
        Record b = new Record();

        new Thread(new Clerk(a, b)).start();
        new Thread(new Clerk(b, a)).start();
    }

    static class Record {
    }

    static class Clerk implements Runnable {

        private Record A, B;

        public Clerk(Record a, Record b) {
            A = a;
            B = b;
        }

        public void run() {
            while (true) {
                System.out.println("in thread " + Thread.currentThread());
                for (int i = 0; i < 10000; i++) {
                    doStuff(A, B);
                }
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException ex) {
                }
            }
        }

        public synchronized void doStuff(Record a, Record b) {
            synchronized (a) {
                synchronized (b) {
                }
            }
        }
    }
}

答案 1 :(得分:3)

如果一个线程用/ b构建,第二个用b / a构建,我希望这会死锁。

在这种情况下,线程会锁定第一个实体,然后锁定第二个实体。如果线程1锁定a并试图锁定b,同时线程2锁定b并等待a,那么它将全部停止。

这是Java tutorial deadlock example,与上面的例子非常相似。