首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >线程有可能死锁自己吗?

线程有可能死锁自己吗?
EN

Stack Overflow用户
提问于 2010-08-16 21:14:04
回答 12查看 13.6K关注 0票数 62

Java中的线程在技术上有可能死锁自己吗?

在不久前的一次面试中,我被问到这个问题,我回答说这是不可能的,但面试官告诉我这是可能的。不幸的是,我不能得到他关于如何实现这个死锁的方法。

这让我开始思考,我能想到的唯一情况是,你有一个RMI服务器进程,其中包含一个调用自身的方法。调用该方法的代码行被放在synchronized块中。

这是可能的吗?还是面试官说错了?

我所考虑的源代码就是这样的( testDeadlock在RMI服务器进程中运行)

代码语言:javascript
复制
public boolean testDeadlock () throws RemoteException {
    synchronized (this) {
        //Call testDeadlock via RMI loopback            
    }
}
EN

回答 12

Stack Overflow用户

回答已采纳

发布于 2010-09-08 17:31:41

JVM只跟踪具有监视器的本地线程,如果调用类在自身内部进行外部回调,则传入调用会导致原始线程自身死锁。

您应该能够运行以下代码来说明这一想法

代码语言:javascript
复制
import java.rmi.*;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.*;

public class DeadlockThreadExample {

    public static interface DeadlockClass extends Remote {
        public void execute() throws RemoteException;
    }

    public static class DeadlockClassImpl extends UnicastRemoteObject implements DeadlockClass {
        private Object lock = new Object();

        public DeadlockClassImpl() throws RemoteException {
            super();
        }

        public void execute() throws RemoteException {
            try {
                System.out.println("execute()::start");

                synchronized (lock) {
                    System.out.println("execute()::Entered Lock");
                    DeadlockClass deadlockClass = (DeadlockClass) Naming.lookup("rmi://localhost/DeadlockClass");
                    deadlockClass.execute();
                }
                System.out.println("execute()::Exited Lock");
            } catch (NotBoundException e) {
                System.out.println(e.getMessage());
            } catch (java.net.MalformedURLException e) {
                System.out.println(e.getMessage());
            }
            System.out.println("execute()::end");
        }
    }

    public static void main(String[] args) throws Exception {
        LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
        DeadlockClassImpl deadlockClassImpl = new DeadlockClassImpl();
        Naming.rebind("DeadlockClass", deadlockClassImpl);
        DeadlockClass deadlockClass = (DeadlockClass) Naming.lookup("rmi://localhost/DeadlockClass");
        deadlockClass.execute();
        System.exit(0);
    }
}

程序的输出如下所示

代码语言:javascript
复制
execute()::start
execute()::Entered Lock
execute()::start

此外,线程转储还显示以下内容

代码语言:javascript
复制
"main" prio=6 tid=0x00037fb8 nid=0xb80 runnable [0x0007f000..0x0007fc3c]
    at java.net.SocketInputStream.socketRead0(Native Method)
    at java.net.SocketInputStream.read(SocketInputStream.java:129)
    at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)
    at java.io.BufferedInputStream.read(BufferedInputStream.java:235)
    - locked <0x02fdc568> (a java.io.BufferedInputStream)
    at java.io.DataInputStream.readByte(DataInputStream.java:241)


"RMI TCP Connection(4)-172.17.23.165" daemon prio=6 tid=0x0ad83d30 nid=0x1590 waiting for monitor entry [0x0b3cf000..0x0b3cfce8]
    at DeadlockThreadExample$DeadlockClassImpl.execute(DeadlockThreadExample.java:24)
    - waiting to lock <0x0300a848> (a java.lang.Object)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)


"RMI TCP Connection(2)-172.17.23.165" daemon prio=6 tid=0x0ad74008 nid=0x15f0 runnable [0x0b24f000..0x0b24fbe8] 
    at java.net.SocketInputStream.socketRead0(Native Method)
    at java.net.SocketInputStream.read(SocketInputStream.java:129)
    at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)
    at java.io.BufferedInputStream.read(BufferedInputStream.java:235)
    - locked <0x02ffb6d8> (a java.io.BufferedInputStream)
    at java.io.DataInputStream.readByte(DataInputStream.java:241)

,这表明线程确实已经设法锁定了自己。

票数 4
EN

Stack Overflow用户

发布于 2010-08-16 21:18:47

这取决于你所说的“死锁”到底是什么意思。例如,您可以很容易地在没有任何脉冲的监视器上执行wait() ...但我认为我不会称之为死锁。

按照你的“调用自己的方法”的思路,如果你的服务器只运行一定数量的线程,它们可能都在忙于等待来自同一服务器的响应,如果这算数的话。(最简单的例子:服务器只使用一个线程进行处理。如果您编写一个请求处理程序来调用同一服务器,它将等待被阻塞的线程完成对请求的处理,然后才能为相同的请求提供服务...)这并不是真正的“同步块”类型的死锁,但这确实是一个需要注意的危险。

编辑:要将此答案应用到其他定义中,此处的竞争操作将是“完成当前请求”和“处理新请求”。每个操作都在等待另一个操作的发生。

票数 20
EN

Stack Overflow用户

发布于 2010-08-16 21:49:31

也许面试官在想的是:

代码语言:javascript
复制
Thread.currentThread().join();

然而,我认为这不能算作死锁。

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3493441

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档