On Fri, 21 Oct 2011 14:32:15 -0400, Alexander <aldem+dm...@nk7.net> wrote:

Hi,

I've the code (see below) which produces an exception (SyncException "Unable to wait for condition") unless "synchronized" is used when waiting on condition (Fedora Linux, 32 bit, DMD 2.055).

Do I do something wrong? Using "synchronized" when accessing anything that is synchronization object
by itself is a little bit counter-intuitive, IMHO.

---snip---
import std.conv;
import std.stdio;
import core.thread;
import core.sync.mutex;
import core.sync.condition;

__gshared Mutex         mutex;
__gshared Condition     cond;

void logs(string text)
{
         synchronized {
                 writeln(text);
         }
}

void worker()
{
         logs("Worker started");
         while (true) {
                 //synchronized (mutex)
                 {
                         try {
                                 cond.wait();
                         } catch (Exception ex) {
                                 logs("Oops: %s" ~ to!string(ex));
                                 return;
                         }
                 }
                 logs("Got notify");
         }
}

void main()
{
         mutex = new Mutex();
         cond = new Condition(mutex);
         (new Thread(&worker)).start();
         (new Thread(&worker)).start();
         (new Thread(&worker)).start();
         (new Thread(&worker)).start();
         Thread.sleep(dur!("msecs")(250));
         logs("Sending notify");
         cond.notifyAll();
         thread_joinAll();
}
---snip---

When waiting on a condition, you must have its associative mutex locked, or Bad Things could happen. You should also have the mutex locked when signaling the condition, but I don't think that's an absolute requirement.

The typical producer-consumer process works like this:

__gshared bool data;

void thread1()
{
   while(1)
   {
      synchronized(mutex)
      {
         if(!data)
         {
             data = true; // produce!
             condition.notify();
         }
      }
   }
}

void thread2()
{
   synchronized(mutex)
   {
      while(!data)
          condition.wait();
      data = false; // consume!
   }
}

The key here is, waiting on a condition atomically unlocks the mutex. If waiting on a condition was allowed without locking the mutex, potentially thread2 could miss thread1's signal, and you encounter a deadlock!

-Steve

Reply via email to