Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/364.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_Multithreading_Deadlock_Rmi - Fatal编程技术网

Java 线程是否可能自行死锁?

Java 线程是否可能自行死锁?,java,multithreading,deadlock,rmi,Java,Multithreading,Deadlock,Rmi,从技术上讲,Java中的线程是否可以自行死锁 不久前我在一次采访中被问到这一点,回答说这是不可能的,但采访者告诉我这是可能的。不幸的是,我无法得到他关于如何实现这个僵局的方法 Deadlock detected ================= "Negotiator-Thread-1": waiting to lock Monitor of com.google.code.tempusfugit.concurrency.DeadlockDetectorTest$Cat@ce4a8a

从技术上讲,Java中的线程是否可以自行死锁

不久前我在一次采访中被问到这一点,回答说这是不可能的,但采访者告诉我这是可能的。不幸的是,我无法得到他关于如何实现这个僵局的方法

Deadlock detected
=================

"Negotiator-Thread-1":
  waiting to lock Monitor of com.google.code.tempusfugit.concurrency.DeadlockDetectorTest$Cat@ce4a8a
  which is held by "Kidnapper-Thread-0"

"Kidnapper-Thread-0":
  waiting to lock Monitor of com.google.code.tempusfugit.concurrency.DeadlockDetectorTest$Cash@7fc8b2
  which is held by "Negotiator-Thread-1"
这引起了我的思考,我能想到的唯一一种情况是,在哪里可以发生这种情况,就是在哪里有一个RMI服务器进程,其中包含一个调用自身的方法。调用该方法的代码行放置在同步块中

这是可能的,还是面试官不正确

我考虑的源代码大致如下(testDeadlock在RMI服务器进程中运行)


这完全取决于你所说的“死锁”是什么意思。例如,您可以轻松地
wait()
在没有任何脉冲的监视器上。。。但我不认为我会称之为僵局

按照您的“调用自身的方法”行思考,如果您的服务器只运行了一定数量的线程,那么它们可能都在忙于等待来自同一服务器的响应(如果这算上的话)。(最简单的示例:服务器仅使用一个线程进行处理。如果您编写一个请求处理程序,调用同一个服务器,它将等待被阻止的线程完成处理请求,然后才能服务于同一个请求…)这并不是真正的“同步块”死锁,但这确实是一个需要注意的危险


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

也许他指的是锁本身,那当然太容易了:

synchronized( this )
{
    wait( );
}

根据以下定义:

死锁是两个或多个相互竞争的操作各自等待另一个完成的情况

我想说的是答案是否定的——一个线程可以无限期地坐在那里等待某件事情,但是除非两个相互竞争的动作在等待对方,否则根据定义,这不是死锁

Deadlock detected
=================

"Negotiator-Thread-1":
  waiting to lock Monitor of com.google.code.tempusfugit.concurrency.DeadlockDetectorTest$Cat@ce4a8a
  which is held by "Kidnapper-Thread-0"

"Kidnapper-Thread-0":
  waiting to lock Monitor of com.google.code.tempusfugit.concurrency.DeadlockDetectorTest$Cash@7fc8b2
  which is held by "Negotiator-Thread-1"
除非有人向我解释一个线程如何同时等待两个操作完成

更新:我能想到的唯一可能的情况是某种消息泵,线程处理一条消息,要求它无限期地等待某事发生,实际上某事将由消息泵上的另一条消息处理


这种(令人难以置信的人为设计)场景在技术上可能被称为死锁。

理想情况下,线程不应该使用“同步锁”自行创建死锁,除非JVM本身真的存在缺陷,就像一些人在旧版本中所说的那样。

根据维基百科,“僵局是指两个或多个相互竞争的行动都在等待对方完成,因此双方都没有完成。”

Deadlock detected
=================

"Negotiator-Thread-1":
  waiting to lock Monitor of com.google.code.tempusfugit.concurrency.DeadlockDetectorTest$Cat@ce4a8a
  which is held by "Kidnapper-Thread-0"

"Kidnapper-Thread-0":
  waiting to lock Monitor of com.google.code.tempusfugit.concurrency.DeadlockDetectorTest$Cash@7fc8b2
  which is held by "Negotiator-Thread-1"
…“在计算机科学中,Coffman死锁是指两个或多个进程各自等待对方释放资源,或两个以上进程在循环链中等待资源时的一种特定情况。”


如果你严格定义的话,我认为两个或两个以上的是这里的关键词。

不,因为Java实现了可重入性。但是请不要把并发性和RMI混为一谈。存根中的同步与内部同步的远程对象完全不同。

可能是什么意思rviewer想到的是:

Thread.currentThread().join();

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

虽然我没有使用Java,但我以前已经死锁了一个单线程应用程序。IIRC:例程a锁定了一段数据来更新它。例程B也锁定了同一段数据来更新它。由于需求变化,a最终调用了B。Oops

Deadlock detected
=================

"Negotiator-Thread-1":
  waiting to lock Monitor of com.google.code.tempusfugit.concurrency.DeadlockDetectorTest$Cat@ce4a8a
  which is held by "Kidnapper-Thread-0"

"Kidnapper-Thread-0":
  waiting to lock Monitor of com.google.code.tempusfugit.concurrency.DeadlockDetectorTest$Cash@7fc8b2
  which is held by "Negotiator-Thread-1"

当然,这只是我第一次尝试运行代码时发现的一个普通的开发错误,但它本身确实存在死锁。我认为这种类型的死锁在任何支持文件系统的语言中都是可能的。

从读锁升级到写锁(在持有读锁的同时尝试获取写锁)将导致线程被完全阻塞。这是死锁吗?由你来判断……但这是用单个线程创建效果的最简单方法


以下是线程死锁的一种方法

public class DeadlockMe
{
    public static void main(String[] args)
    {
        DeadlockThing foo = new DeadlockThing();
        synchronized(foo)
        {
            try
            {
                foo.wait();
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }
    }
}

线程创建一个类的实例(任何类)并等待它。因为线程创建了一个具有本地作用域的对象,所以任何其他线程都不可能通知该对象唤醒线程。

您编写的线程可以接收来自其他线程的消息,例如,通知它终止。您在e线程监视其他线程并向它们发送终止消息并等待响应。该线程会在列表中找到自己,向自己发送一条消息以终止并等待自己终止。如果它的编写方式没有将传入消息优先于等待状态…

如果您扩展术语死锁的定义:单个线程可能会发现自己被先前使用的不可重入锁阻塞。

当线程进入同步块时,它会检查当前线程是否是锁的所有者,如果是,则线程只会继续,而不等待


因此我认为这是不可能的。

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

public class DeadlockMe
{
    public static void main(String[] args)
    {
        DeadlockThing foo = new DeadlockThing();
        synchronized(foo)
        {
            try
            {
                foo.wait();
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }
    }
}
您应该能够运行此代码来说明这个想法

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);
    }
}
程序的输出如下所示

execute()::start
execute()::Entered Lock
execute()::start
此外,线程转储还显示以下内容

"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)
“主”优先级=6 tid=0x00037fb8 nid=0xb8
"main" #1 prio=5 os_prio=0 tid=0x0000000002a52800 nid=0x550c waiting on condition [0x000000000291f000]
   java.lang.Thread.State: WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for  <0x00000007162e5e40> (a java.util.concurrent.locks.ReentrantReadWriteLock$NonfairSync)
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:870)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1199)
    at java.util.concurrent.locks.ReentrantReadWriteLock$WriteLock.lock(ReentrantReadWriteLock.java:943)
    at LiveLock.main(LiveLock.java:10)
import threading

"""
Change RLock to Lock to make it "hang"
"""
lock = threading.Condition(threading.RLock())


def print_list(list):
    lock.acquire()
    if not list:
        lock.release()
        return
    print(list[0])
    print_list(list[1:])
    lock.release()


print_list([1, 2, 3, 4, 5])