Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/362.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 JVM如何确保只有一个线程可以获得对象的锁?_Java_Multithreading_Locking - Fatal编程技术网

Java JVM如何确保只有一个线程可以获得对象的锁?

Java JVM如何确保只有一个线程可以获得对象的锁?,java,multithreading,locking,Java,Multithreading,Locking,我们大多数人都知道,每当线程访问对象的同步块时,JVM就会将该对象的锁提供给线程。 JVM如何确保只有一个线程可以访问对象的锁?JVM为此使用监视模式 JVM使用操作系统提供的一些锁定功能,如信号量对象。因此,现在的问题是操作系统如何做到这一点 通常这些东西都有硬件支持。CPU可以提供一个比较和设置指令,该指令在执行时设置CPU引脚(在多CPU体系结构中有用)或CPU内部线路(对于单CPU多核体系结构),该指令告诉其他硬件地址总线上当前形成的内存位置不会被其他任何人改变。因此,硬件架构保证了该指

我们大多数人都知道,每当线程访问对象的同步块时,JVM就会将该对象的锁提供给线程。
JVM如何确保只有一个线程可以访问对象的锁?

JVM为此使用监视模式


JVM使用操作系统提供的一些锁定功能,如信号量对象。因此,现在的问题是操作系统如何做到这一点

通常这些东西都有硬件支持。CPU可以提供一个比较和设置指令,该指令在执行时设置CPU引脚(在多CPU体系结构中有用)或CPU内部线路(对于单CPU多核体系结构),该指令告诉其他硬件地址总线上当前形成的内存位置不会被其他任何人改变。因此,硬件架构保证了该指令的原子性

一旦有了保证的原子比较和设置指令,剩下的就相对容易了:lock对象有一个标志;希望获取锁的线程对该标志执行值为1的比较和设置指令;如果比较结果为true,则该值已经为1,因此其他一些线程已经拥有锁。如果结果为false,则值不是1,因此当前线程可能认为自己是锁的所有者。


如果操作系统无法代表线程获取锁,则会将线程置于“等待锁定”状态,在此状态下,线程将一直保持,直到释放锁。

有两种不同的低级机制:CAS和等待条件。获取线程不会忙着等待CAS成功。@MarkoTopolnik正确,它不会忙着等待。它将由操作系统的线程调度程序添加到等待获取锁的线程表中,以便在下次重新调度时重新尝试比较和设置指令,这通常会发生在下一个线程切换上。这个故事意味着不管监视器状态如何,线程都会盲目地恢复。我相信系统首先会意识到满足了条件(锁是自由的),然后才选择等待集中的一个线程来运行并获取它。@MarkoTopolnik我不想说任何不同的话。我修改了我的答案,希望把它说得更清楚。如果你认为可以的话,请告诉我。换一句话,我的最后一句话是:系统不会“定期重试”——而是有一个反应过程:当线程释放监视器时,会触发一个过程,从监视器的等待集中选择一个线程,让它恢复并获得锁。至少到目前为止,我的理解是这样的。简单的回答是,JVM要求操作系统这样做。长答案是一个书本级的话题:@jameslarge太糟糕了最好的答案是评论。