Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/xpath/2.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 - Fatal编程技术网

Java 锁定锁后但最终重试前出现异常的可能性

Java 锁定锁后但最终重试前出现异常的可能性,java,multithreading,Java,Multithreading,我想知道给定的代码是否像 lock.lock(); try { count++; } finally { lock.unlock(); } Monitor.Enter(...) try { ... } finally { Monitor.Exit(..) } 在执行lock方法之后,但在进入try finally块之前,是否有可能以某种方式终止执行线程?这将导致一个被占用但从未释放的锁。Java/JVM规范中是否有一行代码可以保证,如果代码是使用这种习惯用法编

我想知道给定的代码是否像

lock.lock();
try {
    count++;
} finally {
    lock.unlock();
}
Monitor.Enter(...)
try
{
    ...
}
finally
{
    Monitor.Exit(..)
}
在执行
lock
方法之后,但在进入
try finally
块之前,是否有可能以某种方式终止执行线程?这将导致一个被占用但从未释放的锁。Java/JVM规范中是否有一行代码可以保证,如果代码是使用这种习惯用法编写的,那么就不可能永远保持锁定状态

我的问题的灵感来源于对C#相关问题的回答,该问题引用了MSDN上的两篇文章

  • 关于类似代码的问题

    lock.lock();
    try {
        count++;
    } finally {
        lock.unlock();
    }
    
    Monitor.Enter(...)
    try
    {
        ...
    }
    finally
    {
        Monitor.Exit(..)
    }
    
    在C#的情况下,基于JIT生成的机器代码,执行永远不会达到
    try finally

    我知道这可能被视为一个做作的问题/吹毛求疵,但我的好奇心战胜了我

    Java/JVM规范中是否有一行给出了一些建议 确保如果代码是使用该习惯用法编写的,则没有 离开的机会永远锁着吗

    首先,我想注意到java中有结构化锁和非结构化锁。结构化锁是一种锁,其中锁定的代码封装在某个结构(块)中,并在该结构(块)的末尾自动释放。同步方法与同步块一样多。在java中,只有在使用同步块的情况下,才能直接以字节码获得monitorenter()指令。因此,如果monitorenter指令失败,那么这将是一个致命错误,将导致jvm停止。使用syncrhonized方法,编译字节码中没有直接的monitorenter和monitorexit指令,但是syncrhonized块中的代码被标记为jvm已同步,jvm将自己完成该工作。所以在这种情况下,如果smth出错,那么这将再次成为一个致命的jvm错误。因此,这里对您的问题的答案是否定的,因为同步块或方法被编译为本机jvm指令,它们的崩溃将导致整个jvm崩溃

    现在让我们来讨论非结构化锁。在这些锁中,您必须通过调用该锁的直接方法来注意锁定和解锁。在这里,您可以通过创建复杂有趣的构造(如链锁等)获得许多优势。同样,你的问题的答案是否定的,实际上,在这个方法中抛出异常是绝对可能的,在这里也绝对可能得到活锁或死锁。所有这些都是可能的,因为非结构化锁定是绝对可编程的java概念。JVM对非结构化锁一无所知。java中的锁是一个接口(),您可以使用OOB非结构化锁,如可重入锁、可重入RW锁等,或者编写自定义实现。但在现实生活中,如果您使用的是例如可重入锁,那么几乎没有机会出现异常。即使是静态分析器也会告诉您,在RLock中没有任何点可以抛出异常(检查为未检查)。但可能的是在那里得到一个错误()。我们再次遇到了一个致命的JVM故障,在此之后您将不需要任何锁。而不是字节码的monitorenter RLock和几乎所有其他OOB java锁都使用AbstractQueuedSynchronizer()。因此,您可以确保它是完全编程的,而JVM对此几乎一无所知

    现在从架构的角度来看。如果在某些实现中,lock方法内部出现意外异常,并且在该异常之后,锁仍然可以继续使用,那么最好在那里获得一个永久有效的锁,而不是内部状态已损坏的锁。使用它不再安全,没有人保证正确的进一步锁定,因为你至少有一个不正确行为的先例。锁中的任何意外异常都应被视为一个问题,在进一步使用之前,需要对其初始原因进行深入调查。而长寿命的锁将阻止其他线程使用它,更重要的是,系统将保持它的正确状态。当然,总有一天smb会发现并发计算通常都是关于正确性的

    关于这个问题:

    执行线程是否有可能以某种方式终止 在执行锁方法之后但在进入try finally块之前


    答案当然是肯定的。您甚至可以挂起持有锁的线程,或者只调用sleep,以便其他线程无法获取锁。锁定算法就是这样工作的,对此我们无能为力。这将被归类为错误。实际上,无锁2+线程算法在这种情况下不易受攻击。并发编程不是一件简单的事情。在设计过程中,您应该考虑很多事情,即使在设计之后,您也无法避免失败。

    可能与原因有关。从未听说过Java中存在像链接中的noop这样的问题,但这当然也依赖于JVM。相关:出于所有实际目的,您可以假设引发了异常且锁未锁定,或者您将进入try块。显然,这排除了JVM突然崩溃之类的情况,在这种情况下,锁发生了什么并不重要……这是一个非常彻底和实用的答案。