Reputation: 41
Basic:
// this.a is a shared variable.
AtomicInteger a = this.a;
int x = a.get();
In a multi-threaded condition, we cannot ensure that x
is 1 because some other thread may call something like a.getAndIncrement()
just before we load the stored value in a
to x
, which cause the final result of x
to be 2.
So, in ThreadPoolExecutor:
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get();
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (!isRunning(recheck) && remove(command))
reject(command);
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
else if (!addWorker(command, false))
reject(command);
}
in the recheck routine:
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (!isRunning(recheck) && remove(command))
reject(command);
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
we read from AtomicInteger ctl
and load it into recheck
. But it also may be changed by other threads at any time. Is there some mechanism which make this recheck to be absolutely reliable? Or do we just need to consider most of the cases?
Below is the occurrence I've talked about which is less possible to happen:
if (isRunning(c) && workQueue.offer(command)) { // RUNNING
int recheck = ctl.get(); // RUNNING
if (!isRunning(recheck) && remove(command)) // RUNNING
reject(command);
else if (workerCountOf(recheck) == 0) // RUNNING and workerCount is 0
// SHUTDOWN by other thread
addWorker(null, false); // SO?
}
My thought: ThreadPools can't be restarted, so the state transmation can't be SHUTDOWN -> RUNNING
. The question then become: if we shutdown the pool while rechecking, and it failed to load the instant state into recheck
, what will happen?
I noticed that when the Pool wants to add a new Worker, it will check the current state again and acquire the mainLock
before adding the worker into workers
. So:
ctl
a variable that is placed in front and used to block most concurrent issues?ctl
variable to exist to avoid excessive acquisition of global locks?Upvotes: 2
Views: 73