none
Why "volatile" key word doesn't work properly in multiple-threads? RRS feed

  • Question

  • I was told by someone that voiltale can be only modified to a common variable when shared by real multiple cores……But How can I know How many real cores have I got now?But my machine is 2-core but variable doesn't work properly in my machine……

    Thursday, July 26, 2012 8:21 AM

Answers

  • volatile keyword instructs compiler that a variable is being acceessed by multiple threads so that no partial read or write occur.  For example, consider the below statement,

    int x = 100;
    int y = 0;
    y = y + x;

    In assembly code the highlighted line might look like below,

    LINE1: mov ah, 100     ;copy 100 into register
    LINE2: mov al, y       ;copy value of y in register
    LINE3: add ah, 10 ;add 10 to ah
    LINE4: mov y, ah ;copy register value into x

    Suppose a thread is executing this statement and it executes only LINE1 & LINE2 and gets suspended. Now another thread comes and executes the same statement. But note that thread1 didn't execute completely so the value of y is still 0. So, second thread will wrongly read the value of y.

    So, volatile keyword ensures that the all the above 4 statements are executed as one statement so that no partial operation may occur resulting in bad read or write.

    No coming to your problem, it is not working because you have not synchronized the two threads and hence, you get odd results. So, take a look at thread synchronization. Then you can modify your code as below,

    class Program
    {
       static object token = new object();
    
       static void Main(string[] args)
       {
           int sum = 0;
           Thread th = new Thread(() => 
           {
              for (int i = 1; i <100000; i++)
              {
                 lock(token)
                 {
                    Thread.VolatileWrite(ref sum, sum - 1);
                 }
              }
           });
    
           th.Start();
           for (int i =1; i < 100000; i++)
           {
               lock(token)
               {
                  Thread.VolatileWrite(ref sum, sum + 1);
               }
           }
     
           th.Join();
           Console.WriteLine(sum);
       }
    }

    I hope this helps.

    Please mark this post as answer if it solved your problem. Happy Programming!

    • Proposed as answer by Mike FengModerator Friday, July 27, 2012 7:41 AM
    • Marked as answer by TimoYang Tuesday, July 31, 2012 9:22 AM
    Thursday, July 26, 2012 1:12 PM
  • The volatile modifier is usually used for a field that is accessed by multiple threads without using the lock statement to serialize access. Using the volatile modifier ensures that one thread retrieves the most up-to-date value written by another thread.

    Read that sentence again.  It doesn't say it causes a lock.  It doesn't say it replaces the need for a lock.  It says the usual use is when there is no lock.

    The very specific example it gives is that one thread is reading what a different thread is writing.  The sample code you've posted here and in the other forum conversation has multple threads doing both reading and writing.  When you do this, you need to serialize the entire update or you will get invalid results.

    volatile ensures that when a variable is read, the reader will see the most recent value at this instant in time.  Without a lock to prevent writes, that value is immediately stale.  The stale value can still be useful to report progress in a GUI or to flag a state change, but it shouldn't be used in calculations that update the original variable.


    This signature unintentionally left blank.

    • Marked as answer by TimoYang Tuesday, July 31, 2012 9:22 AM
    Monday, July 30, 2012 11:23 AM

All replies

  • Number of logical processors can be accessed through following

    Console.WriteLine("Number Of Logical Processors: {0}", Environment.ProcessorCount);

    And number of core can be retried using following

    int coreCnt = 0;
    foreach (var item in new System.Management.ManagementObjectSearcher("Select * from Win32_Processor").Get())
    {
        coreCnt += int.Parse(item["NumberOfCores"].ToString());
    }
    Console.WriteLine("Number Of Cores: {0}", coreCnt);

    The volatile modifier ensures an atomic get-and-set value operations in a multithreaded operating environment and is usually used for a field that is accessed by multiple threads without using the lock statement to serialize access. Using the volatile modifier ensures that one thread retrieves the most up-to-date value written by another thread.


    If this post answers your question, please click Mark As Answer. If this post is helpful please click Mark as Helpful.

    Regards,
    Nair S

    Thursday, July 26, 2012 8:49 AM
  • Hi again,

    Sorry but this codes don't work for me quite well……Why?

     class Program
        {
            static void Main(string[] args)
            {
                int sum = 0;
                Thread th = new Thread(() => 
                {
                    for (int i = 1; i <100000; i++)
                    {
                        Thread.VolatileWrite(ref sum, sum - 1);
                    }
                });
                th.Start();
                for (int i =1; i < 100000; i++)
                {
                    Thread.VolatileWrite(ref sum, sum + 1);
                }
     
                th.Join();
                Console.WriteLine(sum);
            }
        }
    Thursday, July 26, 2012 10:18 AM
  • volatile keyword instructs compiler that a variable is being acceessed by multiple threads so that no partial read or write occur.  For example, consider the below statement,

    int x = 100;
    int y = 0;
    y = y + x;

    In assembly code the highlighted line might look like below,

    LINE1: mov ah, 100     ;copy 100 into register
    LINE2: mov al, y       ;copy value of y in register
    LINE3: add ah, 10 ;add 10 to ah
    LINE4: mov y, ah ;copy register value into x

    Suppose a thread is executing this statement and it executes only LINE1 & LINE2 and gets suspended. Now another thread comes and executes the same statement. But note that thread1 didn't execute completely so the value of y is still 0. So, second thread will wrongly read the value of y.

    So, volatile keyword ensures that the all the above 4 statements are executed as one statement so that no partial operation may occur resulting in bad read or write.

    No coming to your problem, it is not working because you have not synchronized the two threads and hence, you get odd results. So, take a look at thread synchronization. Then you can modify your code as below,

    class Program
    {
       static object token = new object();
    
       static void Main(string[] args)
       {
           int sum = 0;
           Thread th = new Thread(() => 
           {
              for (int i = 1; i <100000; i++)
              {
                 lock(token)
                 {
                    Thread.VolatileWrite(ref sum, sum - 1);
                 }
              }
           });
    
           th.Start();
           for (int i =1; i < 100000; i++)
           {
               lock(token)
               {
                  Thread.VolatileWrite(ref sum, sum + 1);
               }
           }
     
           th.Join();
           Console.WriteLine(sum);
       }
    }

    I hope this helps.

    Please mark this post as answer if it solved your problem. Happy Programming!

    • Proposed as answer by Mike FengModerator Friday, July 27, 2012 7:41 AM
    • Marked as answer by TimoYang Tuesday, July 31, 2012 9:22 AM
    Thursday, July 26, 2012 1:12 PM
  • I know that using lock or Monitor.Enter or InternLock can work?

    But why cannot I ignore it? "volitale" variable can make itself "shared and immediately upgrated"?

    Friday, July 27, 2012 5:10 AM
  • No.. That is not correct. 'volatile' is meant for atomic operations but it doesn't make the object synchronized automatically.


    Please mark this post as answer if it solved your problem. Happy Programming!

    Friday, July 27, 2012 5:14 AM
  • No.. That is not correct. 'volatile' is meant for atomic operations but it doesn't make the object synchronized automatically.


    Please mark this post as answer if it solved your problem. Happy Programming!

    If "atomic operations"——it should upgrate the value automatically immdiately……But not……Why?

    So When to use volatile and when to use lock?Why doesn't my code work properly?

    Friday, July 27, 2012 5:26 AM
  • volatile should be used for a variable which involves in operations like addition which under multithread environment might result in partial operation (like I explain in my first post). But using volatile doesn't prevent multiple threads from performing an operation (on the variable) at the same time, so, still improper read write can happen by threads.

    On the other hand 'lock' ensures only one thread does an operation at any time. Also unlike volatile, lock can be applied to a bunch of statements which are said to be a critical section.

    You code doesn't work because you are not synchronizing two threads.


    Please mark this post as answer if it solved your problem. Happy Programming!

    Friday, July 27, 2012 5:54 AM
  • Volatile is more to ensure that other threads don't use a cached value.

    http://msdn.microsoft.com/en-us/library/x13ttww7(v=vs.100).aspx

    Proper synchronization is still required.

    • Proposed as answer by Rudedog2 Friday, July 27, 2012 3:27 PM
    Friday, July 27, 2012 8:48 AM
    Moderator
  • Deja Vu?

    http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/851b3230-9978-4f0b-ace8-e39c89d66408

    a single atomic operation cannot be interrupted.  However you can be interrupted between atomic operations.  This is when you need to use a locking mechanism.

    volatile does not change this.  volatile just means that the CPU register, L2 cache, and RAM location will all contain the same value before a read begins and after a write ends.


    This signature unintentionally left blank.

    Friday, July 27, 2012 10:39 AM
  • Volatile is more to ensure that other threads don't use a cached value.

    http://msdn.microsoft.com/en-us/library/x13ttww7(v=vs.100).aspx

    Proper synchronization is still required.

    Exactly.  CPUs can have on board cache to minimize the number of R/W operations have to take place with memory.  The volatile keyword instructs the compiler to issue code that causes the processor to always perform a R/W with memory and not use its' on board cache.  This way, all threads and CPUs are always working with the same data stored in the same location.  But, it does nothing to synchronize the access to the data.

    Rudy   =8^D


    Mark the best replies as answers. "Fooling computers since 1971."

    http://thesharpercoder.blogspot.com/

    Friday, July 27, 2012 3:26 PM
  • >>volatile should be used for a variable which involves in operations like addition which under multithread environment might result in partial operation

    I cannot really understand the bold one……Do u mean that it can only sychronized Read or Write, but not Read&Write?Can u give us an example to show how it is used?

    And to the others——

    I know that a thread will have its own memory like cache or something, so the reason why I cannot get the right answer is because the cache cannot be upgrated immediately……Since "volatile" can make all of the multiple threads upgrated immediately,It should work……

    Am I understanding wrongly?

    MANY MANY THANKS AGAIN……

    Saturday, July 28, 2012 3:19 AM
  • Hey everyone——

    MSDN tells us that volatile can be for lock!But that's not really……Is MSDN wrong?

    The volatile modifier is usually used for a field that is accessed by multiple threads without using the lock statement to serialize access. Using the volatile modifier ensures that one thread retrieves the most up-to-date value written by another thread.

    http://msdn.microsoft.com/en-us/library/x13ttww7(v=vs.71).aspx

    Saturday, July 28, 2012 3:39 AM
  • The volatile modifier is usually used for a field that is accessed by multiple threads without using the lock statement to serialize access. Using the volatile modifier ensures that one thread retrieves the most up-to-date value written by another thread.

    Read that sentence again.  It doesn't say it causes a lock.  It doesn't say it replaces the need for a lock.  It says the usual use is when there is no lock.

    The very specific example it gives is that one thread is reading what a different thread is writing.  The sample code you've posted here and in the other forum conversation has multple threads doing both reading and writing.  When you do this, you need to serialize the entire update or you will get invalid results.

    volatile ensures that when a variable is read, the reader will see the most recent value at this instant in time.  Without a lock to prevent writes, that value is immediately stale.  The stale value can still be useful to report progress in a GUI or to flag a state change, but it shouldn't be used in calculations that update the original variable.


    This signature unintentionally left blank.

    • Marked as answer by TimoYang Tuesday, July 31, 2012 9:22 AM
    Monday, July 30, 2012 11:23 AM