[concurrency-interest] Single-threaded ForkJoinPool

cowwoc cowwoc at bbs.darktech.org
Mon Feb 8 05:00:49 EST 2016


You're still vulnerable to the same race condition:

 1. [main] Invokes ForkJoinPool.execute(task)
 2. [WorkerThread] Finishes running a task, reaches the point
    immediately before deregisterThread() at
    https://github.com/scala/scala/blob/2.12.x/src/library/scala/concurrent/impl/ExecutionContextImpl.scala#L61
 3. [main] ForkJoinPool invokes tryAddWorker(),
    https://github.com/scala/scala/blob/2.12.x/src/library/scala/concurrent/impl/ExecutionContextImpl.scala#L65
    returns null
 4. [WorkerThread] Invokes deregisterThread().

Now we have an enqueued task, no worker threads and no one is trying to 
spin up a new thread.

Gili

On 2016-02-08 4:53 AM, Viktor Klang wrote:
> I was thinking something along the lines of this:
>
> https://github.com/scala/scala/blob/2.12.x/src/library/scala/concurrent/impl/ExecutionContextImpl.scala#L65
> https://github.com/scala/scala/blob/2.12.x/src/library/scala/concurrent/impl/ExecutionContextImpl.scala#L68
>
> (no need for WeakReferences to Threads, synchronized etc)
>
> On Mon, Feb 8, 2016 at 8:47 AM, cowwoc <cowwoc at bbs.darktech.org 
> <mailto:cowwoc at bbs.darktech.org>> wrote:
>
>     So, it turns out this solution isn't actually safe.
>
>     1. I used the following thread factory:
>
>                     ForkJoinWorkerThreadFactory factory = new
>     ForkJoinWorkerThreadFactory()
>                     {
>                         private WeakReference<Thread> currentWorker =
>     new WeakReference<>(null);
>
>                         @Override
>                         public synchronized ForkJoinWorkerThread
>     newThread(ForkJoinPool pool)
>                         {
>                             // If the pool already has a live thread,
>     return null.
>                             Thread thread = currentWorker.get();
>                             if (thread != null && thread.isAlive())
>                             {
>                                 System.out.println("Thread: " +
>     thread.getName() + " is already alive, returning null.");
>                                 return null;
>                             }
>                             ForkJoinWorkerThread result = new
>     MyForkJoinWorkerThread(pool);
>                             currentWorker = new WeakReference<>(result);
>                             // According to Doug Lea this will reduce
>     the probability of short livelocks
>                             Thread.yield();
>                             return result;
>                         }
>                     };
>
>     2. I started a debugging session.
>     3. I suspended all threads long enough for the worker thread to
>     get flagged as idle (approximately 10 seconds).
>     4. I allowed all threads to continue execution.
>     5. Upon resuming, the worker thread shut down and at the same time
>     the factory printed "Thread: X is already alive, returning null."
>     6. If I run the above scenario without suspending all threads
>     (only suspending the "main" thread) then the worker thread shuts
>     down, I resume execution, and a new worker thread spins up.
>
>     In other words, the proposed solution is vulnerable to a race
>     condition.
>
>     Gili
>
>     On 2016-02-06 9:35 PM, cowwoc wrote:
>>     Thanks Doug, I'll give this a try.
>>
>>     Thanks,
>>     Gili
>>
>>     On 2016-02-06 3:02 PM, Doug Lea [via JSR166 Concurrency] wrote:
>>>     On 02/06/2016 05:21 AM, Viktor Klang wrote:
>>>     > What happens if you supply it with a thread factory which only
>>>     allows a single
>>>     > thread to be alive at a time, and returns null if it already
>>>     has returned a
>>>     > still living thread?
>>>     >
>>>
>>>     Yes, this will work if you are positive that only one thread
>>>     is required for liveness. FJ sometimes conservatively creates
>>>     threads when it cannot itself guarantee liveness (for example,
>>>     when GC or other system load causes stalls). But it will
>>>     respond to null factory returns by rechecking, not failing.
>>>     unless a thread really is needed to maintain liveness, in which
>>>     case the program may livelock. To reduce transient near-livelock,
>>>     you might want to place a Thread.yield() call before the
>>>     "return null" in the factory.
>>>
>>>     -Doug
>>>
>>>
>>>     > --
>>>     > Cheers,
>>>     > √
>>>     >
>>>     > On Feb 6, 2016 05:19, "cowwoc" <[hidden email]
>>>     <http:///user/SendEmail.jtp?type=node&node=13243&i=0>
>>>     > <mailto:[hidden email]
>>>     <http:///user/SendEmail.jtp?type=node&node=13243&i=1>>> wrote:
>>>     >
>>>     >     Hi,
>>>     >
>>>     >     Is this the correct mailing list for discussing
>>>     ForkJoinPool in JDK9? If
>>>     >     not, please point me to the right place.
>>>     >
>>>     >     I have a feature request for ForkJoinPool which doesn't
>>>     seem to be possible
>>>     >     to implement without a JDK change:
>>>     http://stackoverflow.com/q/34012134/14731
>>>     >
>>>     >     Specifically, I need to be able to an application that
>>>     uses Random and
>>>     >     ForkJoinPool in a deterministic manner when
>>>     debugging/profiling but run
>>>     >     full-speed in normal execution mode. I have all the moving
>>>     parts nailing
>>>     >     down except for ForkJoinPool.
>>>     >
>>>     >     If I create ForkJoinPool with a parallelism of 1,
>>>     sometimes I see two worker
>>>     >     threads getting used. I am guessing that this is caused by
>>>     >     ForkJoinTask.get() invoking
>>>     ForkJoinPool.common.externalHelpComplete(), but
>>>     >     maybe something else is going on.
>>>     >
>>>     >     Is there a way for me to guarantee that ForkJoinThread
>>>     will use exactly 1
>>>     >     worker thread, no less, no more? Would you like me to file
>>>     a formal feature
>>>     >     request?
>>>     >
>>>     >     Thank you,
>>>     >     Gili
>>>     >
>>>     >
>>>     >
>>>     >     --
>>>     >     View this message in context:
>>>     >
>>>     http://jsr166-concurrency.10961.n7.nabble.com/Single-threaded-ForkJoinPool-tp13232.html
>>>     >     Sent from the JSR166 Concurrency mailing list archive at
>>>     Nabble.com.
>>>     > _______________________________________________
>>>     >     Concurrency-interest mailing list
>>>     > [hidden email]
>>>     <http:///user/SendEmail.jtp?type=node&node=13243&i=2>
>>>     <mailto:[hidden email]
>>>     <http:///user/SendEmail.jtp?type=node&node=13243&i=3>>
>>>     > http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>>>     >
>>>     >
>>>     >
>>>     > _______________________________________________
>>>     > Concurrency-interest mailing list
>>>     > [hidden email]
>>>     <http:///user/SendEmail.jtp?type=node&node=13243&i=4>
>>>     > http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>>>     >
>>>
>>>
>>>
>>>     _______________________________________________
>>>     Concurrency-interest mailing list
>>>     [hidden email]
>>>     <http:///user/SendEmail.jtp?type=node&node=13243&i=5>
>>>     http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>>>
>>>
>>>     ------------------------------------------------------------------------
>>>     If you reply to this email, your message will be added to the
>>>     discussion below:
>>>     http://jsr166-concurrency.10961.n7.nabble.com/Single-threaded-ForkJoinPool-tp13232p13243.html
>>>
>>>     To unsubscribe from Single-threaded ForkJoinPool, click here.
>>>     NAML
>>>     <http://jsr166-concurrency.10961.n7.nabble.com/template/NamlServlet.jtp?macro=macro_viewer&id=instant_html%21nabble%3Aemail.naml&base=nabble.naml.namespaces.BasicNamespace-nabble.view.web.template.NabbleNamespace-nabble.view.web.template.NodeNamespace&breadcrumbs=notify_subscribers%21nabble%3Aemail.naml-instant_emails%21nabble%3Aemail.naml-send_instant_email%21nabble%3Aemail.naml>
>>>
>>
>
>
>     ------------------------------------------------------------------------
>     View this message in context: Re: Single-threaded ForkJoinPool
>     <http://jsr166-concurrency.10961.n7.nabble.com/Single-threaded-ForkJoinPool-tp13232p13250.html>
>
>
>     Sent from the JSR166 Concurrency mailing list archive
>     <http://jsr166-concurrency.10961.n7.nabble.com/> at Nabble.com.
>
>     _______________________________________________
>     Concurrency-interest mailing list
>     Concurrency-interest at cs.oswego.edu
>     <mailto:Concurrency-interest at cs.oswego.edu>
>     http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>
>
>
>
> -- 
> Cheers,
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20160208/4411be61/attachment.html>


More information about the Concurrency-interest mailing list