SynchronousQueue

Arkadiusz Gasiński jigga at jigga.pl
Sun Feb 10 22:39:44 UTC 2019


Awesome, thanks Volkan! Makes perfect sense on the second thought.

On Sun, Feb 10, 2019 at 8:32 PM Volkan Yazıcı <volkan.yazici at gmail.com>
wrote:

> Hey Arek,
>
> About your 2nd question, the lock is still held after yielding:
>
> public static void main(String[] args) {
>     ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
>     Lock writeLock = readWriteLock.writeLock();
>     ContinuationScope scope = new ContinuationScope("test");
>     Continuation continuation = new Continuation(scope, () -> {
>         System.out.println("locking");
>         writeLock.lock();
>         try {
>             System.out.println("locked, yielding");
>             Continuation.yield(scope);
>             System.out.println("resuming");
>         } finally {
>             System.out.println("unlocking");
>             writeLock.unlock();
>         }
>     });
>     do {
>         System.out.format("locked? %s%n", readWriteLock.isWriteLocked());
>         continuation.run();
>     } while (!continuation.isDone());
>     System.out.format("locked? %s%n", readWriteLock.isWriteLocked());
> }
>
> produces:
>
> locked? false
> locking
> locked, yielding
> locked? true
> resuming
> unlocking
> locked? false
>
> Hope this helps.
>
> Best.
>
>
> On Sun, Feb 10, 2019 at 7:07 PM Arkadiusz Gasiński <jigga at jigga.pl> wrote:
>
>> Thank you for the clarification. After switching to "traditional" threads
>> and cachedThreadPool, the output was pretty much the same as with
>> singleThreadedExecutor and fibers, so it's definitely the trace messages
>> that caused confusion here.
>>
>> (On a side point, I regret using SQ in the demo as it's not really
>> > suited for fibers at this time. It's really good for transfers between
>> > threads where there is a lot of contention of course. TBD on what should
>> > be done for fibers in this area).
>>
>>
>> I personally liked that example in that it clearly showed the idea behind
>> fibers, i.e. yielding/freeing up carrier thread when it cannot make
>> progress, which was apparent with the singleThreadedExecutor. But would be
>> more than happy to find out what would you replace the SQ example with?
>> I'm
>> actually doing a workshop about project loom for my coworkers next week. I
>> know it's still a prototype, and a lot may change before it's released,
>> but
>> it's really interesting project and current version is stable enough to
>> play with it and explore the possibilities it may/will bring to the
>> platform. The main theme of the workshop will be to reconfigure sample
>> Spring Boot microservice to use Fibers instead of Threads as we work with
>> Boot on the daily basis, but if you think that there is anything in
>> particular that I should touch on when doing this workshop, I'd be
>> thankful
>> for suggestions.
>>
>> One last thing...
>>
>> continuation = new Continuation(scope, () -> {
>>     var lock = new ReentrantReadWriteLock();
>>     lock.readLock().lock();
>>     try {
>>         System.out.println(1);
>>         Continuation.yield(scope);
>>         System.out.println(2);
>>     } finally {
>>         lock.readLock().unlock();
>>     }
>> });
>>
>>
>> It's possible to yield a continuation when holding a
>> j.u.c.l.Lock/ReadWriteLock. It this lock released when yielding and
>> somehow
>> reacquired when continuing?
>>
>> Thanks,
>> Arek
>>
>> On Sun, Feb 10, 2019 at 10:53 AM Alan Bateman <Alan.Bateman at oracle.com>
>> wrote:
>>
>> > On 09/02/2019 12:33, Arkadiusz Gasiński wrote:
>> > > :
>> > > I assumed (as SynchronousQueue has no capacity) that the output would
>> be
>> > > more like:
>> > >
>> > > Produder.offer
>> > > Consumer.take
>> > > Producer.offer
>> > > Consumer.tak
>> > >
>> > > And so on. But in the actual output almost each time 2 tasks are
>> actually
>> > > offered and then 2 tasks are taken. Do you have any idea why this
>> > happens?
>> > I briefly looked at your test and the producer and consumer (sharing one
>> > thread) are running in lockstep, I think it's just the trace messages
>> > that are a bit misleading. The producer prints the "Offering" message
>> > before queue.put. The put doesn't need to block/park when the consumer
>> > is parked/waiting for an element N so it will continue on and print
>> > "Offering" message for element N+1 before it blocks/parks in queue.put.
>> > On the consumer side, it prints "Processing" after queue.take has been
>> > used to remove element N. The producer offering element N+1 has released
>> > the thread to allow the consumer to continue so it will process element
>> > N and continue to take element N+1. If you update the test to print a
>> > trace message before and after both queue.put and queue.take then I
>> > think it will be a bit clearer.
>> >
>> > (On a side point, I regret using SQ in the demo as it's not really
>> > suited for fibers at this time. It's really good for transfers between
>> > threads where there is a lot of contention of course. TBD on what should
>> > be done for fibers in this area).
>> >
>> > -Alan
>> >
>> >
>> >
>> >
>> >
>> >
>>
>


More information about the loom-dev mailing list