假设我有一个像这样的代码片段
synchronized(obj) {
do something;
}
如果obj
已被某个其他线程锁定,则此代码将等到obj
释放,之后它将尝试获取锁定。
但我想知道如果无法立即获得锁定,是否有任何方法可以跳过代码块?
或换句话说,有没有办法检测对象是否已被锁定?
更新:
感谢您提及Lock
界面,但要求程序遵守相同的合同,即它们都引用Lock
对象而不是synchronized
关键字。
我想知道是否有内置的方法来检查锁定状态?
感谢。
答案 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来实现它,它将允许你更多的控制