Live data from Hacker News

We switched to Java 21 virtual threads and got a deadlock in TPC-C for Postgres

blog.ydb.tech

171–180 of 253 posts

Re: We switched to Java 21 virtual threads and got a deadlock in TPC-C for Postgres

#171

Can someone explain what these virtual threads are in 2 sentences please?

They are not real threads. That is, the CPU is not context switching them but jvm running them in async.

Usually threads were also used for long running io but not cpu intensive tasks. It's recommended to use virtual threads for such scenarios now

Re: We switched to Java 21 virtual threads and got a deadlock in TPC-C for Postgres

#172

This problem is not going to go away so easily. Numerous core Java classes (like BufferedInputStream) use synchronized. I count 1600+ usages in java.base. The blocking issue means it's _much_ easier to accidentally run into this, rather than waving it away as an unlikely edge case. I personally ran into this Using the built in com.sun webserver, with a virtual thread executor. My VPS only has two CPUs which means the…

As the JEP states, pinning due to synchronized is a temporary issue. We didn't want to hold off releasing virtual threads until that matter is resolved (because users can resolve it themselves with additional work), but a fix already exists in the Loom repository, EA builds will be offered shortly for testing, and it will be delivered in a GA release soon.

Those who run into this issue and are unable or unwilling to do the work to avoid it (replacing synchronized with j.u.c locks) as explained in the adoption guide [1] may want to wait until the issue is resolved in the JDK.

I would strongly recommend that anyone adopting virtual threads read the adoption guide.

[1]: https://docs.oracle.com/en/java/javase/21/core/virtual-threa...

Re: We switched to Java 21 virtual threads and got a deadlock in TPC-C for Postgres

#173

Can someone explain what these virtual threads are in 2 sentences please?

Why two sentences? Maybe you should ask ChatGPT if you want explanations with specific length requirements.

Anyway it's pretty simple really. A generic thread is bunch of stack frames (with their associated local variables). A standard OS thread is under the control of the kernel scheduler which decides whether the thread runs and makes progress or not. The VirtualThread in Java is just a thread which is not directly mapped to the OS thread scheduler but exists as a user space object that can be scheduled by a (Java implemented) scheduler. It's basically just a call stack with its local variables, but one that only steps forward when an OS thread of the scheduler decides to step it.

Re: We switched to Java 21 virtual threads and got a deadlock in TPC-C for Postgres

#174

Can someone explain what these virtual threads are in 2 sentences please?

They are not real threads. That is, the CPU is not context switching them but jvm running them in async. Usually threads were also used for long running io but not cpu intensive tasks. It's recommended to use virtual threads for such scenarios now

Thanks!

> Why two sentences? Maybe you should ask ChatGPT if you want explanations with specific length requirements.

As you can see, people can do it better. I put a limit on it because I didn't want an explanation of what threads are, just of the difference.

Re: We switched to Java 21 virtual threads and got a deadlock in TPC-C for Postgres

#175

Earlier quoted context omitted.

They are not real threads. That is, the CPU is not context switching them but jvm running them in async. Usually threads were also used for long running io but not cpu intensive tasks. It's recommended to use virtual threads for such scenarios now

Thanks! > Why two sentences? Maybe you should ask ChatGPT if you want explanations with specific length requirements. As you can see, people can do it better. I put a limit on it because I didn't want an explanation of what threads are, just of the difference.

The post you replied to had four sentences. (But two paragraphs).

Re: We switched to Java 21 virtual threads and got a deadlock in TPC-C for Postgres

#176

This problem is not going to go away so easily. Numerous core Java classes (like BufferedInputStream) use synchronized. I count 1600+ usages in java.base. The blocking issue means it's _much_ easier to accidentally run into this, rather than waving it away as an unlikely edge case. I personally ran into this Using the built in com.sun webserver, with a virtual thread executor. My VPS only has two CPUs which means the…

People always forget that things that only happen every few million times, can happen fairly frequently on a busy server. This has bitten me numerous times. The nature of a lot of these types of issues is that they are hard to detect and hard to reproduce. Virtual threads are nice for unblocking legacy code but they aren't without issues. There are better options for new code with less trade offs on the jvm as well.…

> Virtual threads are nice for unblocking legacy code but they aren't without issues. There are better options for new code with less trade offs on the jvm as well.

The designers of Project Loom would say the exact opposite. The whole push behind Project Loom and similar models (Go's oft-praised "goroutines" runtimes being another one) is motivated by Threads being a much better fit for async behavior in a fundamentally procedural language like Java or Go than promise-based frameworks like async/await.

The whole motivation of Project Loom is to make the simple thing (spawning threads to handle blocking IO) the fast thing as well (by actually replacing the blocking IO with efficient async IO OS calls and managing the threads internally). Project Loom will be considered a full success if the next generation Java web server does something akin to "new Thread(() -> {executeHandlerFunc(conn); }.Start(); " for each incoming connection, just like the Go built-in web server.

Re: We switched to Java 21 virtual threads and got a deadlock in TPC-C for Postgres

#177
post #145
post #108

Earlier quoted context omitted.

I dislike the style this particular author chose, but don't object in general. Assuming the images are actually somewhat relevant (or at least funny), I think I'd prefer an AI-generated image over a big wall of text. To each their own, though, of course.

What value does AI slop add though?

What value does a random stock image add?

Re: We switched to Java 21 virtual threads and got a deadlock in TPC-C for Postgres

#178
post #106
post #75

Earlier quoted context omitted.

> This one was a very large caveat pointed out loudly every time the feature was mentioned to the community. It really wasn't. There were people on here, including Oracle employees, claiming that the virtual thread implementation was a drop-in replacement that would work (not necessarily perform better, but work) in all cases.

If your program was prone to deadlock as is, and is just more easily happening with virt threads, it means that the problem is your code.

If your program requires 5 OS threads to be able to make progress (say, there are operations for which 4 threads are blocked while the 5th does work), and the runtime only spawns 2 OS threads and tries to schedule your 5 now virtual threads on those 2 OS threads, then your old program was perfectly correct and the virtual threads runtime has broken it.

This was a known and advertised failure case with the new threads runtime, exacerbated by limitations in the implementation that cause certain blocking operations to block the current OS thread instead of blocking the virtual thread and allowing another virtual thread to be re-use the underlying OS thread.

Re: We switched to Java 21 virtual threads and got a deadlock in TPC-C for Postgres

#179
post #39

This is a common problem when migrating a system from threads to virtual threads. In general, using primitives which block the current thread and prevent forward progress can quickly lead to deadlocks. It’s a hard issue to catch because in the past usually this would get “solved” by spawning a new thread to complete the task but in a world with virtual threads the runtime is usually reluctant to spawn more threads, s…

Is that all that's happening here? There's an implicit limit on real threads, where before it was unlimited by virtue of not using the virtual thread's limited pool? If it doesn't spawn threads when all of them are blocked, that seems kinda dumb. And a severe change in semantics. It can be conservative and try running unpinned ones on fewer threads and shuffle them around and slowly spawn more to ensure eventual prog…

The change in semantics is that while in principle your OS thread will always have a turn at making progress (assuming no super heavy spin locks etc), that isn't true for virtual threads. The classic situation and the one they hit in the article is something like this,

You've got some virtual threads that encounter this code,

    synchronized(foo) {
      foo.wait()
    }
And some other virtual threads that are in charge of awaking the waiters,

    synchronized(foo) {
      operation()
      foo.notify()
    }
This is a classic approach to the producer/consumer pattern in Java.

If operation() can do a virtual thread suspend, then it's possible to be suspended, relinquish the platform thread, which the scheduler reuses for the consumer and gets blocked on Object.wait. If this happens enough, you can end up with all the platform threads blocked, and no threads available to make progress on the producer.

The problem is that Object.wait doesn't release the virtual thread, which is a pretty major foot gun that I think the JDK team would have liked to avoid but it was too hard to implement correctly in the current JDK's codebase.

Re: We switched to Java 21 virtual threads and got a deadlock in TPC-C for Postgres

#180

Earlier quoted context omitted.

People always forget that things that only happen every few million times, can happen fairly frequently on a busy server. This has bitten me numerous times. The nature of a lot of these types of issues is that they are hard to detect and hard to reproduce. Virtual threads are nice for unblocking legacy code but they aren't without issues. There are better options for new code with less trade offs on the jvm as well.…

> Virtual threads are nice for unblocking legacy code but they aren't without issues. There are better options for new code with less trade offs on the jvm as well. The designers of Project Loom would say the exact opposite. The whole push behind Project Loom and similar models (Go's oft-praised "goroutines" runtimes being another one) is motivated by Threads being a much better fit for async behavior in a fundamenta…

I don't know.

My understanding is that that highest performance webserver is nginx. And it uses async internally.

IMO, virtual threads is a better general purpose language feature because it avoids function coloring and is generally easier to reason about, but it may not result in the highest performance Java webserver.

Post reply on HN