Can you spot the Deadlock 4: the solution!

Can you spot the Deadlock 4: the solution!

As most of you correctly highlighted, the last exercise exhibits a deadlock situation. The main thread here simply creates and starts another thread and waits for its completion, but this expectation is never fulfilled.

class Program
{
  static void Main(string[] args)
  {
    var workerThread = new Thread(Worker);
    workerThread.Start();
    workerThread.Join();
  }
...

When one looks at the worker thread code, you realize that the stopping condition is never going to be met: Thread.CurrentThread.IsAlive just cannot be false! The current thread is alive, otherwise it will be dead, hence not executing code.

...
  static void Worker()
  {
    while (Thread.CurrentThread.IsAlive)
    {
      Console.Write("Blah");
    }
  }
}

Based on a true story, this example shows a very common misconception, that the framework provides facilities to control the life cycle of threads, and for that matter that Join will trigger a graceful stop. Well, sorry to break this to you guys, this is just not happening. It is your responsibility to implement an appropriate mechanism.

Here is a valid implementation using a shared flag:

    public class Solution
    {
        private readonly object synchro = new object();
        private bool run;

        static void Main(string[] args) {
            var workerThread = new Thread(Worker);
            run = true;
            workerThread.Start();
            lock (this.synchro) {
                run = false;
            }
            // wait for the thread to start
            workerThread.Join();
        }

        private void Worker() {
            for (;;) {
                lock (this.synchro) {
                    if (!run) {
                        break;
                    }
                }
                Console.Write("Blah ");
            }
        }
    }

New! Available on GitHub: for the curious, the critics and the laziest, I have but the code on GitHub as a VS 2012 solution.

Advertisements

Can you spot the deadlock 4 ?!

Hello everyone,

welcome back to can you spot the deadlock take 4. As a reminder, this a puzzle in a form of multithreaded code. You have to identify the issue that hides in it, usually a deadlock, but not always. Please post your answer in the comments section.

Since it has been a long time since the last episode, let’s start easy!

So what is the problem with this code and how would you fix it?

class Program
{
  static void Main(string[] args)
  {
    var workerThread = new Thread(Worker);
    workerThread.Start();
    workerThread.Join();
  }

  static void Worker()
  {
    while (Thread.CurrentThread.IsAlive)
    {
      Console.Write("Blah ");
    }
  }
}

CYSDL: reboot, your opinion count. Vote!

For those who wonder why there has been no new CYSDL recently, let just say that I have been busy working on the amazing-I-can’t-believe-you’re-not-using-yet assertion library nFluent. But another important factor was I realized that CYSDL quizz needed larger code that may not fit well for the blog format.

For those who may not know Can You Spot The Deadlock, here are some explanations.

As I want to reboot the concept, please answer the following poll.

vv

CYSDL 3: Solution

This is the solution to the Can You Spot the DeadLock 3.

The problem

No deadlock today, this code does not produce the expected result (27000) with certainty. So it raises an explicit exception, most of the time.

why does it occur?

As you have probably guessed, the general intent is to have three agents, each of them responsible for applying a factor (2,3,5) in a sequential way. Sequence is orchestrated thanks to a step counter and the use of modulo so that each agent acts on the appropriate steps.

Expected
Expected Result

The major failure here is the use of if(!condition) instead of while(!condition).
Improper use of the monitor pattern: agents assume that if they are woken up, it means their condition is fulfilled, which is clearly not the case: they are waken for each forward steps. Afterward, it’s a race condition between threads to get the lock.

Sample result
Sample result

As you can see, neither order nor execution count is secured. This code fails in many ways.

how to fix?

You just need to replace the ‘if(!condition)’ with ‘while(!condition)’ and bang, you’re done.

Actually, writing this code was harder than anticipated. My original plan was to use Pulse instead of PulseAll as I feared that PulseAll was giving too much away. But it turns out that all my attempts led to non working code or too obvious problems.

Feel free to submit your own if you want.

And see you for the next exercise.