Re: ForkJoin refresh
Peter Levart via Concurrency-interest <[email protected]>
| Newsgroups | gmane.comp.java.jsr.166-concurrency |
|---|---|
| Message-ID | <[email protected]> |
On 2/6/20 1:31 PM, Doug Lea wrote:
> On 2/5/20 10:15 AM, Peter Levart wrote:
>
>> Would something like the following be more "precise" in targeting the
>> task and only the task and not any other code that executes after the
>> task in the same thread? At least stray interrupts would not be possible
>> as a consequence of cancel(true) for some unrelated task. Should anyone
>> interrupt the pool thread outside of normal task execution, the
>> interrupted status would not propagate to task code nor would it be lost
>> after the task has finished.
>>
> Thanks for taking a look at this. I'm not sure your suggested changes
> are preferable though. Interrupt status for interruptible tasks is
> cleared at end, before running next task, which reduces the impact of
> other slow threads needlessly interrupting the task.
It may reduce the impact, but it can't guarantee that it won't happen.
There is a theoretical race in cancel(true):
1455 if (mayInterruptIfRunning && (t = runner) != null) {
1456 try {
1457 t.interrupt();
1458 } catch (Throwable ignore) {
1459 }
1460 }
...between the read of the 'runner' field and the call to interrupt()
the 't' thread may already transition to running another unrelated task
which will get a stray interrupt then...
If stray interrupts are not problematic, then what about the race that
causes a missing interrupt at the start of execution of the task:
1436 public final boolean exec() {
1437 Thread.interrupted();
1438 runner = Thread.currentThread();
1439 try {
1440 result = callable.call();
1441 return true;
The task might already be executing (just entering exec method), but has
not yet assigned the 'runner' field. A concurrent thread with access to
the task may call cancel(true) which will not interrupt the task,
because it observes the runner still being null. So the task will
execute user code to the end although user code might have checks to
detect interrupts. In my 2nd message I proposed to add a check after
assigning the runner field:
Thread.interrupted();
runner = Thread.currentThread();
try {
// check for concurrent cancel() that just missed the
runner field
if (isCancelled()) {
throw new CancellationException();
} else {
result = callable.call();
}
return true;
The cancelation and the read of 'runner' field in cancel() are reversed,
so this should guarantee that either interrupt is observable by user
code or the task ends execution before it enters user code (Callable):
1452 public final boolean cancel(boolean
mayInterruptIfRunning) {
1453 Thread t;
1454 boolean stat = super.cancel(false);
1455 if (mayInterruptIfRunning && (t = runner) != null) {
1456 try {
1457 t.interrupt();
Regards, Peter
> I can't think of
> cases where it helps to conditionalize this on whether any occurred?
> To better explain though, I'll add to internal documentation that the
> only occurrence of Thread.interrupt inside FJ code itself is during
> termination, in which case tasks are or will be cancelled anyway.
>
> -Doug
>
_______________________________________________
Concurrency-interest mailing list
[email protected]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest