简体   繁体   English

Java 虚拟线程如何知道线程何时等待?

[英]How does a Java virtual thread know when the thread is waiting?

When a virtual thread is blocked due to synchronized call, it's yielding, so the scheduler will unmount it from related Carrier thread.当一个虚拟线程由于同步调用而被阻塞时,它正在让出,所以调度器会从相关的 Carrier 线程中卸载它。

I was wondering, how does a virtual thread know that it's currently at wait state and it's time to yield?我想知道,一个虚拟线程如何知道它当前正在等待 state 并且该让步了?

It appears that you have a slight misconception: When a virtual thread is blocked due to synchronization, it is in fact yielding, but the scheduler will not unmount it from the related carrier thread.看来你有一个小小的误解:当一个虚拟线程因为同步而被阻塞时,它实际上是在屈服,但调度器不会从相关的载体线程中卸载它。 Instead, the carrier thread will be blocked, yielding.相反,载体线程将被阻塞,屈服。 This is one of the current shortcomings of Project Loom , and it is well documented.这是Loom 项目当前的缺点之一,并且有据可查。 The team says they might fix it in the future.该团队表示他们可能会在未来修复它。

Specifically, in Coming to Java 19: Virtual threads and platform threads by Nicolai Parlog 2022-05 we read:具体来说,在Coming to Java 19: Virtual threads and platform threads by Nicolai Parlog 2022-05 我们读到:

Unfortunately, there's one more imperfection in the initial virtual thread proposal: When a virtual thread executes a native method or a foreign function or it executes code inside a synchronized block or method, the virtual thread will be pinned to its carrier thread.不幸的是,最初的虚拟线程提案还有一个不完善之处:当虚拟线程执行本地方法或外部 function或者它在同步块或方法内执行代码时,虚拟线程将被固定到其载体线程。 A pinned thread will not unmount in situations where it otherwise would.固定线程不会在原本应该卸载的情况下卸载。

(Emphasis mine.) (强调我的。)

Further down in the same article, we read:在同一篇文章的下方,我们读到:

[...] a good alternative to synchronization is a ReentrantLock. [...] 同步的一个很好的替代方法是 ReentrantLock。

Note that I have read the same things in a number of other official sources of information, not just from the above blog post.请注意,我在许多其他官方信息来源中阅读了相同的内容,而不仅仅是从上面的博客文章中。

This means that at least for now, if you want to avoid blocking the carrier thread, you must refrain from using the synchronized keyword;这意味着至少现在,如果你想避免阻塞承载线程,你必须避免使用synchronized关键字; instead, you must use a ReentrantLock or some other runtime library class that blocks waiting for something to happen while yielding, such as CountdownLatch etc.相反,您必须使用ReentrantLock或其他一些运行时库 class 来阻止在屈服时等待某些事情发生,例如CountdownLatch等。

So, to answer your question of "how does a Java virtual thread know when the thread is waiting?"因此,要回答您的问题“Java 虚拟线程如何知道线程何时等待?” the answer is that all the classes that provide block waiting while yielding (even the Sleep() method of Thread ) have been modified in Java 19 so that they now co-operate with the virtual threads mechanism precisely so as to allow unmounting from the carrier thread.答案是在 Java 19 中修改了所有提供块等待同时让出的类(甚至是ThreadSleep()方法),以便它们现在与虚拟线程机制精确协作,以便允许从载体上卸载线。

At appropriate places in the code, the blocking is detected.在代码的适当位置,检测到阻塞。 For example例如

  public static void parkNanos(Object blocker, long nanos) {
        if (nanos > 0) {
            Thread t = Thread.currentThread();
            setBlocker(t, blocker);
            try {
                if (t.isVirtual()) {
                    VirtualThreads.park(nanos);<====
                } else {
                    U.park(false, nanos);
                }
            } finally {
                setBlocker(t, null);
            }
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM