State of Loom

Ron Pressler ron.pressler at oracle.com
Fri May 22 22:58:16 UTC 2020


 
You are correct that by scheduling many virtual threads onto a single platform thread,
e.g. with:

  Thread.builder().virtual(Executors.newSingleThreadExecutor()).factory()

you could enforce a total memory ordering, where the "happens-before” relation is
total. This means that you could, say, use a HashMap instead of a ConcurrentHashMap, 
and wouldn't need to use locks (but you could!).

This is what I meant when I wrote, "custom schedulers could choose to provide 
stronger guarantees [than JMM]." How advisable is this? Well, let's file it under 
"advanced usage." But you can certainly try and report back on your experience.

— Ron


On 22 May 2020 at 16:26:07, Mike Rettig (mike.rettig at gmail.com(mailto:mike.rettig at gmail.com)) wrote:

> Moving beyond the AWT example, my main point is about using a single
> carrier thread as a solution to slow blocking operations on a single
> thread. There is a lot of code in the java ecosystem that is written
> using a single thread that guarantees thread safe access to data
> structures and ordered event processing. UI threads and actor
> implementations are two examples. I think it was a wise decision to
> rename loom fibers as virtual threads. Using a single thread as a
> carrier provides a good example as to why they behave like threads.
> For actors, the preferred implementation would be to use a single
> virtual thread for the lifetime of the actor rather than a virtual
> thread per message. Just like a ui thread, there can still be slow
> events that block the thread. With a virtual thread per event, loom
> would choose when and how events get scheduled and potentially
> reordered. As a developer, I'd rather choose how slow events are
> handled and introduce asynchronous handling where necessary.
>  
> Mike
>  
> On Wed, May 20, 2020 at 12:36 PM Alan Bateman wrote:
> >
> > On 20/05/2020 16:55, Mike Rettig wrote:
> > > The UI code I've seen will have problems with out of order executions.
> > >
> > > Consider this psuedocode and how it could execute with loom vs a
> > > single threaded executor:
> > >
> > > ui.execute(()->{
> > > log.info("disabling user input");
> > > lockUserInput("Please Wait. Calculating totals");
> > > });
> > >
> > > final Totals totals = calculations();
> > >
> > > ui.execute(()->{
> > > refresh(totals);
> > > unlockUserInput();
> > > });
> > >
> > > Loom will ensure the UI is reponsive when blocked, but at the
> > > complexity of out of order executions. In my experience, any design
> > > that has the potential to reorder changes to some shared state is best
> > > avoided. IMO, backing virtual threads with a single thread is an
> > > anti-pattern. The thread is still susceptible to pinning, but now out
> > > of order executions are added to the mix. The code needs to be written
> > > as if it is multi-threaded, but at runtime it doesn't get the benefits
> > > of parallel execution.
> > I realize this is pseudocode but I'm wondering whether to read
> > "ui.execute(...)" as invokeLater or invokeAndWait or something else?
> >
> > As Ron had as an example, you could specify EventQueue::invokeLater as
> > the scheduler to enlist the AWT EventQueue dispatch thread as a carrier
> > thread but it usefulness might be limited. Code executed by a virtual
> > thread mounted on the AWT EventQueue dispatch thread would execute in
> > the context of a virtual thread and EventQueue.isDispatchThread() would
> > return false.
> >
> > -Alan



More information about the loom-dev mailing list