Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/349.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 此代码如何导致死锁?_Java_Scjp - Fatal编程技术网

Java 此代码如何导致死锁?

Java 此代码如何导致死锁?,java,scjp,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); } }

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

}
然后


答案是这段代码会导致死锁,但我不明白-这到底有多可能?有人能帮我弄清楚吗?

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

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) {
                }
            }
        }
    }
}
公共类Test1{
公共静态void main(字符串[]args){
记录a=新记录();
记录b=新记录();
新线程(新职员(a,b)).start();
新线程(新职员(b,a)).start();
}
静态课堂记录{
}
静态类Clerk实现Runnable{
私人档案A、B;
书记(记录a、记录b){
A=A;
B=B;
}
公开募捐{
while(true){
System.out.println(“in-thread”+thread.currentThread());
对于(int i=0;i<10000;i++){
多斯塔夫(A,B);
}
试一试{
睡眠(1000);
}捕获(中断异常例外){
}
}
}
公共同步作废文件(记录a、记录b){
已同步(a){
已同步(b){
}
}
}
}
}

如果一个线程是用a/b构造的,而第二个线程是用b/a构造的,我认为这会死锁

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


以下是与上述示例非常相似的示例。

这是不可能的。这些字段被称为
A
B
,但是
run()
使用
A
B
,因此代码甚至不会编译。:)在我看来,代码不会死锁,但当您在第二个构造函数调用中切换a和b时,它可能(而且很可能会)(假设您修复了@minitech注意到的问题)对不起,我没有正确地复制问题:)现在是compiles+1,我怀疑问题被错误地复制到了某个地方。为什么反转参数会导致死锁?@Lewsterin:一个人可以锁定
a
,然后在它锁定
b
之前,另一个已经有了,但正在等待
a
…然后这就是吃饭哲学家的问题,不是吗?@lewsterin如果它锁定
记录b=new记录()第一个,因为在第二个线程中
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) {
                }
            }
        }
    }
}