Is the dead end of starvation here in code?
//code taken from java concurrency in practice
package net.jcip.examples;
import java.util.concurrent.*;
public class ThreadDeadlock
{
ExecutorService exec = Executors.newSingleThreadExecutor();
public class LoadFileTask implements Callable<String> {
private final String fileName;
public LoadFileTask(String fileName) {
this.fileName = fileName;
}
public String call() throws Exception {
// Here where we would actually read the file
return "";
}
}
public class RenderPageTask implements Callable<String>
{
public String call() throws Exception
{
Future<String> header, footer;
header = exec.submit(new LoadFileTask("header.html"));
footer = exec.submit(new LoadFileTask("footer.html"));
String page = renderBody();
// Will deadlock -- task waiting for result of subtask
return header.get() + page + footer.get();
}
}
}
This code takes Java concurrency in practice, and according to the authors, this is where the "ThreadStarvtionDeadlock" happens. Help me find how ThreadStarvationDeadlock happens here and where? Thanks in advance.
Deadlock and starvation occurs on the following line:
return header.get() + page + footer.get();
AS?
This will happen if we add additional code to the program. Perhaps 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 leading to deadLock:
- The task is dispatched
exec
to render the page through theCallable
implemented classRenderPageTask
. -
exec
launchedRenderPageTask
in a separateThread
, only oneThread
that would perform other tasks sent inexec
sequentially. - Inside the
call()
methodRenderPageTask
toexec
go two more tasks. FirstLoadFileTask("header.html")
, and the second -LoadFileTask("footer.html")
. But since the ExecutorServiceexec
, obtained through the codeExecutors.newSingleThreadExecutor();
, as mentioned here , it uses a single worker thread work with an unlimited queueThread , and the thread is already selected RenderPageTask, therefore,LoadFileTask("header.html")
andLoadFileTask("footer.html")
will be put in place in the unlimited all expecting that there will be executed thisThread
. -
RenderPageTask
returns a string containing the concatenation of outputLoadFileTask("header.html")
, page body, and outputLoadFileTask("footer.html")
. These three parts arepage
successfulRenderPageTask
. But the other two parts can only be obtained after both tasks are completed by one dedicated threadExecutorService
. And Thread will be free only after thecall()
method returnsRenderPageTask
. But thecall
methodRenderPageTask
will only return after returningLoadFileTask("header.html")
andLoadFileTask("footer.html")
. Thus, not allowing youLoadFileTask
to perform, leads to Fasting . And every task waiting for another task to complete results in a DeadLock
Hopefully this explains why the deadlock of starvation occurs in the above code.
source to share
The executor I can see is the only executor of the thread and has two tasks to complete. However, these two tasks are independent of each other, and the order of execution seems unimportant. Hence, the return statement will only stop at Future.get to do as much of one and then another task as possible.
This will not be a dead end in the code you are showing.
However I see another task in the code (RenderPageTask), it is not clear which executor is actually running their code. If it is the same executor of the same thread, a deadlock is possible because the two submitted tasks cannot be processed until the main task returns (and this task can only return after two tasks have been processed).
source to share
The reason is not very obvious from the code itself, but from the original book where the code is copied: RenderPageTask dispatches two additional tasks to the Executor to get the page header and footer ...
If RenderPageTask were a task independent of newSingleThreadExecutor, there would be no deadlock at all.
source to share