获取和释放 java 监视器锁(同步块、可重入锁等)是否需要上下文切换到内核 space?

Does acquiring and releasing java monitor locks (synchronized blocks, reentrant locks etc) requires context switch to kernel space?

AFAIK,Java 中的每个对象都有一个标记词。第一个字(标记字)用于存储锁定信息,如果只有一个线程正在获取锁,则通过标志或如果不同线程之间存在争用,则指向锁监视器对象,在这两种情况下,比较和交换构造用于获取锁。

但根据这个 link - https://www.baeldung.com/lmax-disruptor-concurrency

To deal with the write contention, a queue often uses locks, which can cause a context switch to the kernel. When this happens the processor involved is likely to lose the data in its caches.

我错过了什么?

synchronized 和标准 Lock 实现都不需要在锁定 uncontended 或解锁时将上下文切换到内核。这些操作确实归结为原子 cas 或写。

性能关键方面是争用,即当试图获取监视器或锁时它不可用。等待监视器或锁的可用性意味着将线程置于等待状态并在资源可用时重新激活它。性能影响如此之大,您根本不需要担心 CPU 缓存。

出于这个原因,典型的实现执行一定量的旋转,重新检查监视器的可用性或锁定一段时间的循环,当有机会在那个时间变得可用时。这通常与 CPU 核心的数量有关。当资源在那个时候可用时,这些成本就可以避免。但是,这通常需要允许获取 不公平 ,因为旋转获取可能会超过已经等待的线程。

请注意,链接文章在您引用的句子之前说:

Queues are typically always close to full or close to empty due to the differences in pace between consumers and producers.

在这种情况下,较快的线程迟早会进入等待状态,等待队列中的新 space 或新项目,即使它们在没有争用的情况下获得了锁。所以在这种特定场景下,使用简单的队列实现时,相关成本确实存在并且无法避免。