Java tryLock方法-非阻塞方法?

Java tryLock方法-非阻塞方法?,java,concurrency,Java,Concurrency,tryLock方法的文档说明它是一种非阻塞方法 它允许您获取/获取锁(如果在调用该方法时可能) 但我想知道:你怎么能在获得锁的同时仍然保证 你的方法(tryLock)是非阻塞的?!获取锁意味着您是 试图访问一段受保护的代码,因此它应该被阻止(如果你运气不好 i、 e.至少在某些情况下,您应该阻止)。有人能解释一下逻辑吗 在这背后?纯粹从逻辑的角度来看:我不太明白这怎么可能 完全可以完成(确保方法不会阻塞)。除非他们使用另一个 线程当然在tryLock本身的代码中 获取锁意味着您正试图访问受保护

tryLock
方法的文档说明它是一种非阻塞方法
它允许您获取/获取锁(如果在调用该方法时可能)

但我想知道:你怎么能在获得锁的同时仍然保证
你的方法(
tryLock
)是非阻塞的?!获取锁意味着您是
试图访问一段受保护的代码,因此它应该被阻止(如果你运气不好
i、 e.至少在某些情况下,您应该阻止)。有人能解释一下逻辑吗
在这背后?纯粹从逻辑的角度来看:我不太明白这怎么可能
完全可以完成(确保方法不会阻塞)。除非他们使用另一个
线程当然在tryLock本身的代码中

获取锁意味着您正试图访问受保护的代码段,因此它应该阻止(如果您运气不好,即至少在某些情况下应该阻止)

如果这是你想要的行为,你应该使用这种方法。
tryLock
的全部要点是,如果锁不可用,您不想阻止时可以使用它

就如何实现这一点而言,这取决于各个实现——因此您应该看看您感兴趣的实现。我个人认为,对于那些在内部使用
synchronized
的人来说是合理的,如果他们知道
synchronized
块中从来没有运行过用户指定的代码-换句话说,它可以在内部内部进行短暂的阻塞,但不能在锁本身的持续时间内


当然,一个能够访问适当的机器级指令的实现也可以使用比较和交换等。。。见鬼,这可能是一个非常简单的版本。

这些机制的大多数实现都使用所谓的CAS CPU指令来执行基于变量的原子操作。CAS意味着比较和交换。这些函数关注变量的值,如果它是您期望的值,您可以更改它。这提供了一种线程安全(非阻塞/锁定)的方法来对多线程数据进行比较

CAS指令以原子方式执行以下操作:

private int stored = 0;
public int compareAndSwap(int expectedValue , int newValue)

   if(expectedValue == stored)
       stored = newValue;

   return stored;
}
这些非阻塞机制通常只是重试上述函数,直到成功为止(返回的值是预期值)。因为重试循环非常短,所以每次迭代时线程中断的机会很小(或者在实践中,OS调度器甚至会使其不可能)

实际的java锁(
Lock
只是它们实现的接口)都要复杂得多,因为它们提供了额外的特性。但本质上,CAS机制是大多数非阻塞线程安全类的基础


如果您对锁定的内部工作方式感兴趣,这是一个很好的来源。从Java并发性可以做的事情开始,逐步了解它是如何做的。(即使对于非java程序员来说,它也是一个很好的源代码)。您的问题将在第15章中处理。

在大多数现代CPU上,这是使用CAS(比较和交换)@fge完成的。我的意思是:Java是如何完成的?我试着研究代码,但我还不太明白。你是说他们用的是本地方法吗?我以为他们只使用“原语”
wait
notify
notifyAll
。但如果是这样,那么,逻辑上。。。我真的不知道该怎么做,我怀疑大多数JVM都是这样做的,是的(虽然未经验证,所以不要相信我的话);可能不是直接的汇编代码,但是像Linux上的futexes这样的东西可以用来实现这一效果。1)“它可以短暂地阻止内部事务,但不能阻止锁本身”>>>这也是一种猜测(因此我写道:“除非他们在tryLock本身的代码中使用另一个线程”);2) 比较数据集>>>好的,但是这一个本身是非阻塞的吗?如果是的话,它是如何实现的?!我会研究一下。谢谢你至少指出了一些方向。@peter.petrov:我没有考虑在
tryLock
中使用另一个线程。。。听起来你应该基本上看一下
原子类的实现,它很可能依赖于特定于平台的机器代码。在2)>>>是的,好的,那一个在不安全的类上使用了一个本机方法:public final native boolean compareAndSwapInt。我想我现在明白了。谢谢所以它是由本机代码完成的。我的问题是,仅仅通过使用Java并发原语(如
wait
notify
notifyAll
)是否可以做到这一点。在我看来,除非tryLock本身使用另一个线程,否则这是不可能的(要检查锁是否空闲,请非常短暂地阻塞,如果不幸运,请不要获取锁并以非阻塞方式返回)。@peter.petrov:是的,你可以这样做,只要你不介意阻塞足够长的时间来执行内务管理。你不需要一个新的线程,你可以在一个只用于内务管理的监视器上同步。@monkjack当然你是对的,谢谢。(请注意,某些版本的CAS还返回布尔值以指示是否更改)。