Java中是否存在一种快速失败的同步方式?

时间:2012-04-21 02:46:08

标签: java concurrency

假设我有一个像这样的代码片段

synchronized(obj) {
    do something;
}

如果obj已被某个其他线程锁定,则此代码将等到obj释放,之后它将尝试获取锁定。

但我想知道如果无法立即获得锁定,是否有任何方法可以跳过代码块?

或换句话说,有没有办法检测对象是否已被锁定?

更新:

感谢您提及Lock界面,但要求程序遵守相同的合同,即它们都引用Lock对象而不是synchronized关键字。

我想知道是否有内置的方法来检查锁定状态?

感谢。

2 个答案:

答案 0 :(得分:16)

  

Java中是否存在一种快速失败的同步方式?

我认为使用“快速失败”来描述你在这里要做的事情是一个糟糕的术语选择。快速失败意味着不立即获取锁定是失败或应用程序错误; C.F.失败的快速迭代器抛出未经检查的CCME。这不是锁通常提供的语义模型,特别是这里。一个更好的术语是“非阻塞”

此外,尚不清楚静默跳过一段代码,因为您无法获取锁定是有用的行为。在大多数情况下,应用程序需要知道已经采用“跳过”路径。

除了这些要点之外,你不能使用原始对象锁。

(好吧,在某些JVM上你可以使用sun.misc.Unsafe来做这件事,但这是一个非常糟糕的主意。你可能会发现你的编译器,类加载器或安全沙箱会阻止你使用Unsafe API ...应该。此外,此API不会被称为“不安全”!)

java.util.concurrent.locks.Lock API有一种方法可以让您尝试锁定而不会阻塞。具体来说,tryLock()方法尝试获取锁定,并在锁定正在使用时立即返回false

还有其他更高级别的并发类可以用作ersatz锁;例如Semaphore


  

或换句话说,有没有办法检测对象是否已被锁定?

实际上,这有点不同......也不完全有用。当然,你可以(假设)测试是否持有锁。 (事实上​​,一些Lock类明确地支持这一点。)但这并不意味着你可以保证能够在不阻塞的情况下获得锁定。如果你做出(不正确的)假设,你已经在你的代码中引入了一个Heisenbug。


  

我想知道是否有内置的方法来检查锁定状态?

[假设你指的是原始锁...]

不,没有。至少,不在运行的应用程序本身内。 (调试代理可以执行此操作,但是应用程序与其JVM的调试代理进行通信是不切实际的。)

如果您想/需要做这种事情,那么您就没有没有真正的选项,这些选项不涉及更改应用程序的锁定机制。就是这样。

答案 1 :(得分:0)

你可以使用java.util.concurrent.Semaphore来实现它,它将允许你更多的控制