Channels ▼

Arnon Rotem-Gal-Oz

Dr. Dobb's Bloggers

Rendezvous Thread Synchronization

August 04, 2009

I am currently implementing Reservation (a pattern for  “partial temporary commitment” when using Sagas).The  implementation calls for calling a few of the saga members asking them to reserve an asset. Since network calls can take some time I wanted to make each call on its own thread, collect any errors (failures to reserve or communication exceptions) and then have all the threads reconverge to the initiating thread  where any problems will be sorted out (e.g. by retrying the reservation). It basically looks something like the figure below:

image

As you can probably guess this type of synchronization is called Rendezvous (as the threads “meet”). It is also actually fairly easy to implement in .NET I usually do something along the lines of the code snippet below and things like Parallel.For in C# 4.0  will give a similar effect

 

  1.       private void DispatchThreads(List<Thread> threads, List<SharedContext> sharedContexts, ParameterizedThreadStart threadFunction)
  2.         {
  3.             //initiate threads
  4.             foreach (var context in sharedContexts)
  5.             {
  6.                 var dispatchThread = new Thread(threadFunction);
  7.                 threads.Add(dispatchThread);
  8.                 dispatchThread.Start(context);
  9.             }

  10.             //Rendezvous
  11.             foreach (var dispatchThread in threads)
  12.                 dispatchThread.Join();

  13.         \

However, that’s not why I am writing this post. It turns out I have a more complicated situation. In my setup the code of “Main Thread” (in the figure above) can be run by multiple different threads which are initiated by external events (i.e. I don’t control when they run) – What I needed to to is to make sure that if there are several threads that run in parallel they need to wait for the last of them to finish one section of the code before they can all move on. To explain this better consider the figure below:imageThread 1 starts, sometime after that Thread 2 starts and then Thread 3 starts as well – Thread 1 and Thread 2 have to hold and wait until Thread 3 finished. Thread 4 starts beyond the Rendezvous so none of the other threads care about it. Had it started just before Thread 3 finished all the threads would have had to wait for it as well. Basically I need a similar effect to chords in polyphonic C#

I couldn’t find anything that .NET 3.5 for this - It is kind of what ManualResetEvent – however, it not quite that, since we need to wait for the event only when we’re done. Also we need to let other threads “know” we are running so that they’d wait for us. So indeed I wrapped a ManualResetEvent with a few methods to do just that and ended up with the following.

  1. public class Rendezvous
  2.     {
  3.         private readonly ManualResetEvent Synch = new ManualResetEvent(true);
  4.         private readonly object Locker = new object();
  5.         private int Counter = 0;


  6.         /// <summary>
  7.         /// Join the Rendezvous - Mark that a thread is active and it should finish before the others can continue
  8.         /// </summary>
  9.         public void MarkStart()
  10.         {
  11.             lock (Locker)
  12.             {
  13.                 if (Counter < 0) Counter = 0;
  14.                 Counter++;
  15.                 Synch.Reset();
  16.             }
  17.         }

  18.         /// <summary>
  19.         /// Allows a thread to wait for others without having the others wait for it
  20.         /// </summary>
  21.         public void Wait()
  22.         {
  23.             Synch.WaitOne();
  24.         }

  25.         /// <summary>
  26.         ///
  27.         /// </summary>
  28.         public void MarkFinishAndWait()
  29.         {
  30.             lock (Locker)
  31.             {
  32.                 if (--Counter <= 0) Synch.Set();
  33.             }
  34.             //it is ok if we context switch and lock since we want to synchronize the end times
  35.             Wait();
  36.         }
  37.     \

As long as all the threads have access to the same instance of the Rendezvous class they can synchronize their end times.

Rendezvous is a common pattern for workflow systems (also known as Join-And). It is the first time I had to do that in C# with uncontrolled/uncoordinated thread starts so I don’t know how useful it would be to you. However I thought it is also interesting reading so I published it anyway :)

Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 


Video