4

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

synchronized(obj) {
    do something;
}

如果obj已经被其他线程锁定,则此代码将等待直到obj释放,然后它会尝试获取锁定。

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

或者换一种说法,有没有办法检测一个对象是否已经被锁定?

更新:</p>

感谢您提到Lock接口,但这要求程序遵守相同的约定,即它们都引用Lock对象而不是synchronized关键字。

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

谢谢。

4

2 回答 2

16

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

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

此外,由于无法获取锁而静默跳过代码块是一种有用的行为,这一点也不清楚。在大多数情况下,应用程序需要知道已采用“跳过”路径。

撇开这些点不谈,你不能使用原始对象锁来做到这一点。

(好的,在某些 JVM 上您可能可以使用它sun.misc.Unsafe来执行此操作,但这是一个非常糟糕的主意。您可能会发现您的编译器、类加载器或安全沙箱会阻止您使用UnsafeAPI ......因为它应该这样做。此外,这个 API 并不是无缘无故被称为“不安全”的!)

java.util.concurrent.locks.LockAPI 有一个方法允许您尝试在不阻塞的情况下获得锁。具体来说,该tryLock()方法尝试获取锁并false在锁正在使用时立即返回。

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


或者换一种说法,有没有办法检测一个对象是否已经被锁定?

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


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

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

不,没有。至少,不在正在运行的应用程序本身内。(调试代理可以做到这一点,但应用程序与其 JVM 的调试代理对话是不切实际的。)

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

于 2012-04-21T02:54:04.327 回答
0

你可以使用 java.util.concurrent.Semaphore 来实现它,它会让你有更多的控制权

于 2012-04-21T02:55:26.183 回答