在通过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();
答案说这段代码可以导致死锁,但我不明白 - 这究竟是怎么可能的?有人可以帮我解决这个问题吗?
答案 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,与上面的例子非常相似。