Not resuming Virtual Threads?
Ron Pressler
ron.pressler at oracle.com
Mon Jul 6 10:52:52 UTC 2020
So the downside of this approach is that you would need to use AWT’s specific
scheduler rather than create one with java.awt.EventQueue::invokeLater, but
code that’s dependent on a specific scheduling behaviour should be rare and
it seems reasonable that such code would also want full control over the scheduler
so that it can enforce its scheduling policies, rather than ask for a scheduler
with some properties that, if not satisfied, will cause code to fail in truly mysterious
ways.
There is no safe set of assumptions about scheduling that can be exposed to user
code, or, rather, there shouldn’t be. In practice, there can be no scheduling point
in the middle of a bytecode instruction, but I’m not yet sure if it’s best to specify that
or just continue relying on the JMM in general, and let visibility to be strengthened
by scheduling (e.g. if your scheduler has one worker, then memory operations
among the virtual threads scheduled by that scheduler are totally-ordered rather
than partially-ordered).
If you want to forbid scheduling points in critical regions, use locks. And if
your scheduler has stronger visibility than JMM, then you can use custom
locks that don’t require fences or CASes. Giving users even finer-grained control
would complicate matters, and is of questionable utility in Java, where the VM
is highly nondeterministic in the first place (although it is also questionable how
deterministic code written even in a low-level language like C, C++ or Zig and
running on top of a non-realtime kernel really is).
— Ron
On 6 July 2020 at 10:03:04, Johannes Kuhn (info at j-kuhn.de) wrote:
On 06-Jul-20 0:02, Ron Pressler wrote:
Ah, so one thing we are considering is not exactly this, but rather
boolean isScheduledBy(Executor scheduler)
which might be more general as well as more stable. After all,
there could be situations where the carrier thread changes between
the time you query and the time you want to make use of the
information.
Good point. Well, the magic of multi-thread programming in a single thread.
I noticed that some internal APIs use currentCarrierThread() - is there a set of "safe" operations that could be done and not fear that the thread will yield?
One possible use for this is for UI. AWT could expose a thread scheduler
that schedules virtual threads onto the UI thread. Such a method would
allow enforcing that certain UI operations are done either on the UI
thread or on virtual threads scheduled by the UI scheduler.
— Ron
For me, the EDT is a stand in for other similar things - native or not.
AWT has the benefit that it is included in the JDK and most people are somewhat familiar with it.
I don't say AWT should use Virtual Threads for dispatch - but a library similar to AWT may decide to do so.
You can easily create an Executor to execute things on the EDT today with `Executor e = java.awt.EventQueue::invokeLater`.
Problem here is the identity of the lambda (that is explicitly NOT specified).
I did take a look at `EventQueue.isDispatchThread()` - in the end it does something like `return Thread.currentThread() == <expression that returns the EDT>`.
So my approach was to make it possible to change that behavior - if the library (in this case AWT) desires to do so.
Leads to the question if this would break some of the symmetry with `EventQueue.invokeLater()`. I don't really know. Have to think about it more.
- Johannes
More information about the loom-dev
mailing list