Java 此代码如何导致死锁?
通过SCJP6考试模拟器时,我发现如下问题: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); } }
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) {
}
}
}
}
}