AutoResetEvent, ManualResetEvent vs Monitor
Asked Answered
M

3

19

Lets say I have to orchestrate a synchronization algorithm in .Net 3.5 SP1 and any of the synchronization primitives listed in the title fit perfectly for the task.

From a performance perspective, is any single one of those more performant than the others?

I ask this because I have been coding for a while now, but without proper knowledge on the subject.

Merriweather answered 11/11, 2009 at 18:31 Comment(2)
Just write a test app that times their performance.Effulgent
A monitor (and equivalently the C# lock statement) maintains an internal queue, guaranteeing that threads are released in the same order they are blocked. Auto/Manual reset events are much simpler and don't have this overhead.Zap
J
6

If you can, go with Monitor. It's similar to a CRITICAL_SECTION. AutoResetEvent/ManualResetEvent might have slightly more overhead, since these can be shared by different processes, whereas a Monitor belongs to a single process.

Jordonjorey answered 11/11, 2009 at 18:48 Comment(3)
Auto reset events are not shared between processes (mutexes are). But they are native Windows objects and you may run into trouble if you use too many of them.Backdate
From msdn.microsoft.com/en-us/library/ms682400(VS.85).aspx looks like AutoReset can be shared too. At least there's nothing preventing you from creating an Auto event with a name but AutoResetEvent and ManualResetEvent do not let you pass a 'name'.Jordonjorey
Just use the baseclass EventWaitHandle. AutoResetEvent and ManualResetEvent are just constructor wrappers, the only thing they do is calling the constructor from EventWaitHandle either with EventResetMode.AutoReset or EventResetMode.ManualReset...Lundgren
L
19

WaitHandles look very similar to Wait/Pulse Constructs, but the difference is in detail: The WaitHandles Set method, sets the Signal even if no thread is waiting. This means if you call Set in a thread and then call WaitOne in another thread on the same waithandle afterwards, the second thread will continue. Wait and Pulse are different, Pulse only signals a thread that is already in the waiting queue. This means if you call Pulse in a thread and then call Wait in another thread on the same object afterwards, the second thread will wait forever (deadlock). You've got to be extremely carefull if using Wait and Pulse, only use it if you know what you are doing otherwise you might just be lucky...

To create the behaviour of a WaitHandle yourself using Monitor, weather AutoReset or ManualReset, you've got to do way more than a simple Wait/Pulse Construct. Just use the Tools you need to get the Job done:

If you can't synchronize threads with simple locking or atomic operations, think of using WaitHandles. If you can't synchronize threads with WaitHandles, think of using Wait and Pulse.

Lundgren answered 18/2, 2010 at 12:8 Comment(3)
I don't share your concerns about using Wait/Pulse. It's easy to use them correctly without risking deadlocks. Wait/Pulse are core building blocks for signaling between threads, and their performance can be superior to *ResetEvent, because, as Gonzalo correctly notes, the latter can be used for inter process signaling, incurring an overhead.Chowchow
@Eugene: incorrect usage of Wait/Pulse will easily result in a deadlock. Even the MSDN example for the Monitor.Pulse method has a race condition. If the second thread in their example manages to start before the first one, it will deadlock.Antebi
Just wanted to add that the link provided by EugeneBeresovksy in his first comment is one of the best starting points if you want to get into .NET Threading.Lundgren
J
6

If you can, go with Monitor. It's similar to a CRITICAL_SECTION. AutoResetEvent/ManualResetEvent might have slightly more overhead, since these can be shared by different processes, whereas a Monitor belongs to a single process.

Jordonjorey answered 11/11, 2009 at 18:48 Comment(3)
Auto reset events are not shared between processes (mutexes are). But they are native Windows objects and you may run into trouble if you use too many of them.Backdate
From msdn.microsoft.com/en-us/library/ms682400(VS.85).aspx looks like AutoReset can be shared too. At least there's nothing preventing you from creating an Auto event with a name but AutoResetEvent and ManualResetEvent do not let you pass a 'name'.Jordonjorey
Just use the baseclass EventWaitHandle. AutoResetEvent and ManualResetEvent are just constructor wrappers, the only thing they do is calling the constructor from EventWaitHandle either with EventResetMode.AutoReset or EventResetMode.ManualReset...Lundgren
J
2

Wait and pulse are fine, if you follow some simple rules:

  1. You may not bother to lock if if locking isn't needed for your object and you can tell in advance that it's ready; if, however, it looks like you'll have to wait, you must acquire the lock and then make certain you still really do have to wait before you actually do it; you should also in most cases assume that you may randomly be woken up whether or not conditions are ready, so you should recheck the conditions every time you wake up and re-wait if needed.
  2. A pulse must be given after conditions have been set up that will allow waiting code to continue.
  3. If you have something like a "quit" flag, it may be helpful to have every piece of code that acquires the lock test the quit flag after releasing the lock and, if the flag is set, reacquire the lock and send a pulse. You could then have a quit routine set the flag, try acquiring the lock with zero timeout, and send a pulse only if the lock could be acquired. If the acquisition failed, you could be assured some other piece of code will send the necessary pulse. This will avoid any possibility of the 'quit' routine getting stuck at the lock.
Janeyjangle answered 26/10, 2010 at 16:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.