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.

+3


source to share


3 answers


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 the Callable

    implemented class RenderPageTask

    .
  • exec

    launched RenderPageTask

    in a separate Thread

    , only one Thread

    that would perform other tasks sent in exec

    sequentially.
  • Inside the call()

    method RenderPageTask

    to exec

    go two more tasks. First LoadFileTask("header.html")

    , and the second - LoadFileTask("footer.html")

    . But since the ExecutorService exec

    , obtained through the code Executors.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")

    and LoadFileTask("footer.html")

    will be put in place in the unlimited all expecting that there will be executed this Thread

    .
  • RenderPageTask

    returns a string containing the concatenation of output LoadFileTask("header.html")

    , page body, and output LoadFileTask("footer.html")

    . These three parts are page

    successful RenderPageTask

    . But the other two parts can only be obtained after both tasks are completed by one dedicated thread ExecutorService

    . And Thread will be free only after the call()

    method returns RenderPageTask

    . But the call

    method RenderPageTask

    will only return after returning LoadFileTask("header.html")

    and LoadFileTask("footer.html")

    . Thus, not allowing you LoadFileTask

    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.
+11


source


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).

0


source


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.

0


source







All Articles