0

While passing SCJP6 exam simulator I found question like this:

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

}

then

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

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

Answer says that this code can cause deadlock, but I don't get it - how exactly is that possible? Can someone can help me figure that out?

Charles
  • 50,943
  • 13
  • 104
  • 142
Dmitry Zaytsev
  • 23,650
  • 14
  • 92
  • 146
  • 3
    It's not possible. The fields are called `A` and `B`, but `run()` uses `a` and `b`, so the code won't even compile. :) – Ry- Dec 11 '12 at 15:23
  • 2
    Looks to me like that code won't deadlock, but when you switch a and b in the second constructor call it could (and most likely will) (assuming you fix the issue noticed by @minitech) – Mark Rotteveel Dec 11 '12 at 15:24
  • Sorry, I've not copied question correctly :) Now it is compiles – Dmitry Zaytsev Dec 11 '12 at 15:28

2 Answers2

9

Apart from the fact that it does not compile, there is no deadlock in that code. This code could definitely create a deadlock:

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

So if the question is: could the Clerk class be the source of the deadlock? Then the answer is yes.

EDIT

Short example that should deadlock fairly fast. If a and b are used like in the original question, the program runs fine.

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) {
                }
            }
        }
    }
}
assylias
  • 321,522
  • 82
  • 660
  • 783
3

I would expect this to deadlock if one thread was constructed with a/b, and the second with b/a.

In this situation a thread would put a lock on the first entity and the then on the second. If thread 1 locked a and tried to lock b, and thread simultaneously 2 locked b and waited for a, then it would all grind to a halt.

Here's the Java tutorial deadlock example, which is very similar to the above example.

Brian Agnew
  • 268,207
  • 37
  • 334
  • 440