Producer-consumer with a variation - How to synchronize with thread signal / wai...
source link: https://www.codesd.com/item/producer-consumer-with-a-variation-how-to-synchronize-with-thread-signal-wait.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Producer-consumer with a variation - How to synchronize with thread signal / wait?
While working on a large project I realized I was making a lot of calls to be scheduled in the future. Since these were fairly light-weight, I thought it might be better to use a separate scheduler.
ThreadPool.QueueUserWorkItem (() =>
{
Thread.Sleep (5000);
Foo (); // Call is to be executed after sometime
});
So I created a separate scheduler class that runs on its own thread and executes these events. I have 2 functions that access a shared queue from separate threads. I'd use a lock, but since one of the threads needs to sleep-wait, I wasn't sure how to release the lock.
class Scheduler
{
SortedDictionary <DateTime, Action> _queue;
EventWaitHandle _sync;
// Runs on its own thread
void Run ()
{
while (true)
{
// Calculate time till first event
// If queue empty, use pre-defined value
TimeSpan timeDiff = _queue.First().Key - DateTime.Now;
// Execute action if in the next 100ms
if (timeDiff < 100ms)
...
// Wait on event handle for time
else
_sync.WaitOne (timeDiff);
}
}
// Can be called by any thread
void ScheduleEvent (Action action, DataTime time)
{
_queue.Add (time, action);
// Signal thread to wake up and check again
_sync.Set ();
}
}
- The trouble is, I'm not sure how to synchronize access to the queue between the 2 functions. I can't use a monitor or mutex, because Run() will sleep-wait, thus causing a deadlock. What is the right synchronization mechanism to use here? (If there a mechanism to atomically start the sleep-wait process and immediately release the lock, that might solve my problem)
- How can I verify there is no race-condition?
- Is this a variation of the producer consumer problem, or is there a more relevant synchronization problem-description?
While this is somewhat geared towards C#, I'd be happy to hear a general solution to this. Thanks!
OK, take 2 with Monitor/Pulse.
void Run ()
{
while (true)
{
Action doit = null;
lock(_queueLock)
{
while (_queue.IsEmpty())
Monitor.Wait(_queueLock);
TimeSpan timeDiff = _queue.First().Key - DateTime.Now;
if (timeDiff < 100ms)
doit = _queue.Dequeue();
}
if (doit != null)
; //execute doit
else
_sync.WaitOne (timeDiff);
}
}
void ScheduleEvent (Action action, DataTime time)
{
lock (_queueLock)
{
_queue.Add(time, action);
// Signal thread to wake up and check again
_sync.Set ();
if (_queue.Count == 1)
Monitor.Pulse(_queuLock);
}
}
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK