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