//code taken from java concurrency in practice
package net.jcip.examples;
import java.util.concurrent.*;
public class ThreadDeadlock
{
ExecutorServi
Deadlock & Starvation is occurring at following line:
return header.get() + page + footer.get();
HOW?
It will happen if we add some extra code to the program. It might be this one:
public void startThreadDeadlock() throws Exception
{
Future <String> wholePage = exec.submit(new RenderPageTask());
System.out.println("Content of whole page is " + wholePage.get());
}
public static void main(String[] st)throws Exception
{
ThreadDeadLock tdl = new ThreadDeadLock();
tdl.startThreadDeadLock();
}
Steps that leading to deadLock:
exec
for Rendering the page via Callable
implemented class RenderPageTask
.exec
started the RenderPageTask
in separate Thread
, the only Thread
that would execute other tasks submitted to exec
sequentially .call()
method of RenderPageTask
two more tasks are submitted to exec
. First is LoadFileTask("header.html")
and second is LoadFileTask("footer.html")
. But since the the ExecutorService exec
obtained via code Executors.newSingleThreadExecutor();
as mentioned here uses a single worker thread operating off an unbounded queueThread and the thread is already allocated to RenderPageTask , So LoadFileTask("header.html")
and LoadFileTask("footer.html")
will be en queued to the unbounded queue waiting for there turn to be executed by that Thread
.RenderPageTask
is returning a String containing the concatenation of output of LoadFileTask("header.html")
, body of page and output of LoadFileTask("footer.html")
. Out of these three parts page
is obtained successfully by RenderPageTask
. But other two parts can only be obtained after both tasks are executed by the single Thread allocated by ExecutorService
. And Thread will be free only after call()
method of RenderPageTask
returns . But call
method of RenderPageTask
will return only after LoadFileTask("header.html")
and LoadFileTask("footer.html")
is returned. So Not letting LoadFileTask
to execute is leading to Starvation . And each task waiting for other task for completion is leading to DeadLock
The executor I see is a single thread executor and it gets two tasks to do. However these two tasks are not dependent on each other and they order of execution seems not important. Hence the return statement will only pause in Future.get calls as much as required to complete one and then another task.
It will be no deadlock in the code you show.
However I see one more task in the code (RenderPageTask), it is not clear which executor is actually running its code. If it is the same single thread executor, then deadlock is possible as the two submitted tasks cannot be processed before the main task returns (and this task can only return after the two tasks have been processed).
The reason is not very obvious from the code itself but from the original book where the code is copied from: RenderPageTask submits two additional tasks to the Executor to fetch the page header and footer...
If the RenderPageTask were a task independent from the newSingleThreadExecutor, there would be no deadlock at all.