DotNet, Multithreading

Volatile and Thread.MemoryBarrier


Volatile variable and Thread.MemoryBarrier method use in condition when you want to access variable across threads without putting lock.

You can read more about Volatile and Thread.MemoryBarrier on MSDN.

Volatile keyword:


Excerpts from MSDN

The volatile modifier is usually used for a field that is accessed by multiple threads without using the lock statement to serialize access.

The volatile keyword can be applied to fields of these types:

  • Reference types.

  • Pointer types (in an unsafe context). Note that although the pointer itself can be volatile, the object that it points to cannot. In other words, you cannot declare a "pointer to volatile."

  • Types such as sbyte, byte, short, ushort, int, uint, char, float, and bool.

  • An enum type with one of the following base types: byte, sbyte, short, ushort, int, or uint.

  • Generic type parameters known to be reference types.

  • IntPtr and UIntPtr.

    The volatile keyword can only be applied to fields of a class or struct. Local variables cannot be declared volatile


Thread.MemoryBarrier Method

MemoryBarrier is memory fence which prevents any kind of instruction reordering or caching around that fence.

A good approach is to start by putting memory barriers before and after every instruction that reads or writes a
shared field, and then strip away the ones that you don’t need. If you’re uncertain of any, leave them in. Or
better: switch back to using locks!


 

class MemoryBarrierExample
    {
        int _valueTobeSet;
        bool _flag;

        public void RunOnThread1()
        {
            _valueTobeSet = 1900;
            _flag= true;
         }
        public void RunOnThread2()
        {
            if (_flag)
            {
                Console.WriteLine(_valueTobeSet);
            }
        }
    }

If method “RunOnThread1” and “RunOnThread2” run in concurrently on different threads, it might possible that output is “0” because compiler/CLR may do caching optimizations like assignment of variable in one thread would not visible in other threads right away. This may happen mostly on multiprocessor system.

If you put MemoryBarrier before and after reading and writing value to variable, most updated value can be available in all threads.

class MemoryBarrierExample
    {
        int _valueTobeSet;
        bool _flag;

        public void RunOnThread1()
        {
            _valueTobeSet = 1900;
	    Thread.MemoryBarrier();
            _flag= true;
	    Thread.MemoryBarrier();
         }
        public void RunOnThread2()
        {
		Thread.MemoryBarrier();
            if (_flag)
            {Thread.MemoryBarrier();
                Console.WriteLine(_valueTobeSet);
            }
        }
    }

You can also achieve this functionally by using “lock” but lock is associate performance penalty.

Note: you can also introduce memory barriers by using Thread.VolatileRead/Thread.VolatileWrite (these two methods successfully replace thevolatile keyword), Thread.MemoryBarrier, or even with the C# lock keyword etc.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s