Don't get C# volatile the wrong way

By Jerome at August 05, 2004 11:45 Tags: ,

Don't get the C# volatile the wrong way. There is a lot of blurriness around synchronization issues in .NET, especially around the Memory Barriers, System.Monitor, the lock keyword and stuff like this.

It is common to have objects that are able to create Unique identifiers, by mean of a index incremented each time a new value is retreived. It would, using a simplistic view, look like this :

   public class UniqueIdentifier  
  
{     
    
private static int _currentIndex = 0;
    
public int NewIndex
     {         
      
get 
        
       
{

        
return _currentIndex++;
      
}
     }
   }

This is pretty straightforward: Each time the NewIndex property is called, a new index is returned.

But there is a problem in a multithreaded environment, where multiple threads can call the NewIndex at the same time. If we look at the code generated for the getter, here is what we have:

  IL_0000:  ldsfld     int32 UniqueIdentifier::_currentIndex
  IL_0005:  dup
  IL_0006:  ldc.i4.1
  IL_0007:  add
  IL_0008:  stsfld     int32 UniqueIdentifier::_currentIndex

One thing about the multithreading in general, the system can stop the execution anywhere it wants, especially between the operation at 0 and the end of the operation at 8. The effect is pretty obvious : If during this stop time, some other thread executes that same piece of code, each thread ends up with the same "new" index, each one incrementing from the same index. This scenario is in the presence of a uni-processor system, which interleaves the execution of running threads. On multi-processor systems, threads do not even need to be stopped to have this exact same problem. While this is harder that kind of race condition on a uniprocessor, this is far more easier to fall into with multiple processors.

This is a very common problem when programming in multithreaded environments, which is generally fixed by means of synchronization mecanisms like Mutexes or CriticalSections. The whole operation needs to be atomic which means executed by at most one thread at a time.

In the native world, in C/C++ for instance, the language does not provide any "built-in" synchronization mecanisms and the programmers have to do all the work by hand. The .NET framework with C#, on the other hand, provides that kind of mecanisms integrated in the language : the volatile and lock keywords.

A common and incorrect interpretation of the volatile keyword is to think that all operations (opposed to accesses) on a volatile variables are synchronized. This generally leads to this kind of code :

   public class UniqueIdentifier
  
{
    
private static volatile int _currentIndex = 0;
    
public int NewIndex
    
{
      
get
       
{
        
return _currentIndex++;
      
}
     
}
  
}

While this code is valid, it does not fix the synchronization problem encountered. The correct interpretation of the volatile keyword is that read and write operations to a volatile fields must not be reordered and, that the value of the variable must not be cached.

On a single x86 processor system, the only effect of the volatile keyword is that the value is never cached in something like a register and is always fetched from the memory. Since there is only one set of caches and one processor, there is no risk to have inconsistencies where memory would have been modified elsewhere. (This is called processor Self-Consistency)
But, on a multiprocessor system, each processor has a data cache set and depending on the cache policy, an updated value for the variable might not be written back immediatly into the main memory to make it available to the other threads requesting it. In fact it may never be updated, depending on the cache policy. Actually, this kind of situation is really hard to reproduce because of the high utilization of the cache and frequent flushes.

Back to volatile, it means that read/write operations will always target the main memory. In practice, a volatile read or write is called a Memory Barrier. Then, when using a volatile variable the thread is sure to have the latest value.
Back to our example, while we are sure to have the latest value, the read/increment/write operation is still not atomic and can be interrupted right in the middle.

To have a correct implementation of this UniqueIndentifier generator, we have to make it atomic :

   public class UniqueIdentifier
  
{
    
private static int _currentIndex = 0;
    
private object _syncRoot = new object();
    
public int NewIndex
    
{
      
get
      
{
        
lock(_syncRoot)

         
{

          
return _currentIndex++;

         
}

      
}

     
}

  
}

In this example, we are using the lock keyword. This is pretty nice because it uses the System.Threading.Monitor class to create a scope that can be entered by one thread at a time. While this solves the atomicity problem, you might notice that the volatile keyword is not present anymore. This is where the Monitor does something under the hood : It does a memory barrier at the acquisition of the lock and an other one a the release of the lock.

A lot of implicit stuff done by the CLR and it can be pretty hard to catch up on all this. Besides, the x86 memory model is pretty strong and does not introduce a lot of race conditions, while it would on a weaker memory model like the one on Itanium.

As a conclusion, use lock and forget volatile. :)

By the way, this article is pretty interesting on the subject.

SyncProxy, an implicit synchronizer

By Jerome at April 04, 2004 11:51 Tags: , ,

A few days ago, I ran into an MVP article on the MSDN talking about synchronizing asynchronous calls to WebServices heading back to the GUI. Since asynchronous calls are processed in separate threads, it is not safe to call GUI methods directly from these. The article was describing how to create some sort of helper class (some call this an Agent or Pattern) that allows to hide the call to BeginInvoke, freeing the developper from creating many small methods that would only contain calls to BeginInvoke.

Back in dotnetSoul, I did not have to call WebServices - at least not in a repetitive way - but I had to synchronize calls from events generated by the netsoul core. These events are fired from asynchronous read operations on a network stream, which implies that consuming these from the GUI requires to synchronize the call to update some controls.

The old fashion way is to register a "standard" method which only calls the synchronous method via BeginInvoke with the same parameters :

    _chatRoom.UserJoined += new EventHandler(OnChatRoomUserJoined);

...

    private void OnChatRoomUserJoined(object sender, EventArgs args)
    {
         BeginInvoke(new SyncEventHandler(SyncChatRoomUserJoined), new object[]{ sender, args });
    }

    private void OnChatRoomUserJoined(object sender, EventArgs args)
    {
         // call the UI from there...
    }

What a waste of time and error prone way of doing many GUI synchronous calls, since the netsoul core exposes about 20+ events to consumers. You might notice I'm using a SyncEventHandler delegate. I'm using this delegate to avoid the BeginMethod to change the parameters passed in.

So reminding the class used to synchronize the calls to the UI, I though I could create some sort of Proxy class that could be used to both register the event and create the instance of the proxy. I then came up with this :

using System;
using System.Windows.Forms;

namespace Epitech.NetSoul.UI
{
    public delegate void SyncEventHandler(object sender, EventArgs args);

    public class SyncProxy
    {
        private Control             _control;
        private SyncEventHandler    _syncHandler;
        private EventHandler        _asyncHandler;

        public SyncProxy(Control control, SyncEventHandler syncHandler)
        {
            _control        = control;
            _syncHandler    = syncHandler;
            _asyncHandler   = new EventHandler(AsyncHandler);
        }

        // Implicit operator to allow an easy registering on events
        public static implicit operator EventHandler(SyncProxy proxy)
        {
            return proxy._asyncHandler;
        }

        // The asynchronous delegate, which calls the synchronous delegate through
        // BeginInvoke, if required.

        private void AsyncHandler(object sender, EventArgs args)
        {
            if(_control.InvokeRequired)
            {
                _control.BeginInvoke(_syncHandler, new object[]{ sender, args });
            }
            else
            {
                _syncHandler(sender, args);
            }
        }
    }
}

Which can be used like this :

    _chatRoom.UserJoined += new SyncProxy(this, new SyncEventHandler(OnChatRoomUserJoined));

This call creates the proxy then registers the asynchronous delegate from the proxy through an implicit cast to EventHandler. This way, there is only one event handler to create inside the destination form per event handled.

About me

My name is Jerome Laban, I am a Software Architect, C# MVP and .NET enthustiast from Montréal, QC. You will find my blog on this site, where I'm adding my thoughts on current events, or the things I'm working on, such as the Remote Control for Windows Phone.