提交 3d1573d8 编写于 作者: D dl

7035020: ForkJoinPool.invoke may deadlock if parallelism = 1

Reviewed-by: chegar
上级 e6afd818
...@@ -791,18 +791,19 @@ public class ForkJoinPool extends AbstractExecutorService { ...@@ -791,18 +791,19 @@ public class ForkJoinPool extends AbstractExecutorService {
/** /**
* Tries to enqueue worker w in wait queue and await change in * Tries to enqueue worker w in wait queue and await change in
* worker's eventCount. If the pool is quiescent, possibly * worker's eventCount. If the pool is quiescent and there is
* terminates worker upon exit. Otherwise, before blocking, * more than one worker, possibly terminates worker upon exit.
* rescans queues to avoid missed signals. Upon finding work, * Otherwise, before blocking, rescans queues to avoid missed
* releases at least one worker (which may be the current * signals. Upon finding work, releases at least one worker
* worker). Rescans restart upon detected staleness or failure to * (which may be the current worker). Rescans restart upon
* release due to contention. Note the unusual conventions about * detected staleness or failure to release due to
* Thread.interrupt here and elsewhere: Because interrupts are * contention. Note the unusual conventions about Thread.interrupt
* used solely to alert threads to check termination, which is * here and elsewhere: Because interrupts are used solely to alert
* checked here anyway, we clear status (using Thread.interrupted) * threads to check termination, which is checked here anyway, we
* before any call to park, so that park does not immediately * clear status (using Thread.interrupted) before any call to
* return due to status being set via some other unrelated call to * park, so that park does not immediately return due to status
* interrupt in user code. * being set via some other unrelated call to interrupt in user
* code.
* *
* @param w the calling worker * @param w the calling worker
* @param c the ctl value on entry * @param c the ctl value on entry
...@@ -823,7 +824,7 @@ public class ForkJoinPool extends AbstractExecutorService { ...@@ -823,7 +824,7 @@ public class ForkJoinPool extends AbstractExecutorService {
else if (w.eventCount != v) else if (w.eventCount != v)
return true; // update next time return true; // update next time
} }
if (parallelism + (int)(nc >> AC_SHIFT) == 0 && if ((int)c != 0 && parallelism + (int)(nc >> AC_SHIFT) == 0 &&
blockedCount == 0 && quiescerCount == 0) blockedCount == 0 && quiescerCount == 0)
idleAwaitWork(w, nc, c, v); // quiescent idleAwaitWork(w, nc, c, v); // quiescent
for (boolean rescanned = false;;) { for (boolean rescanned = false;;) {
...@@ -893,7 +894,8 @@ public class ForkJoinPool extends AbstractExecutorService { ...@@ -893,7 +894,8 @@ public class ForkJoinPool extends AbstractExecutorService {
w.parked = false; w.parked = false;
if (w.eventCount != v) if (w.eventCount != v)
break; break;
else if (System.nanoTime() - startTime < SHRINK_RATE) else if (System.nanoTime() - startTime <
SHRINK_RATE - (SHRINK_RATE / 10)) // timing slop
Thread.interrupted(); // spurious wakeup Thread.interrupted(); // spurious wakeup
else if (UNSAFE.compareAndSwapLong(this, ctlOffset, else if (UNSAFE.compareAndSwapLong(this, ctlOffset,
currentCtl, prevCtl)) { currentCtl, prevCtl)) {
...@@ -1175,7 +1177,7 @@ public class ForkJoinPool extends AbstractExecutorService { ...@@ -1175,7 +1177,7 @@ public class ForkJoinPool extends AbstractExecutorService {
ws[k] = w; ws[k] = w;
nextWorkerIndex = k + 1; nextWorkerIndex = k + 1;
int m = g & SMASK; int m = g & SMASK;
g = k >= m? ((m << 1) + 1) & SMASK : g + (SG_UNIT<<1); g = k > m? ((m << 1) + 1) & SMASK : g + (SG_UNIT<<1);
} }
} finally { } finally {
scanGuard = g; scanGuard = g;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册