Sharing data across threads
-
Consider the following: namespace Lesson2 { class Program { static void Main(string[] args) { System.Threading.ThreadStart oThreadStart; oThreadStart = new System.Threading.ThreadStart(UpdateCount); System.Threading.Thread[] oThreads; oThreads = new System.Threading.Thread[10]; for (int i = 0; i < oThreads.Length; i++) { oThreads[i] = new System.Threading.Thread(oThreadStart); oThreads[i].Start(); } // Wait for them to complete for (int i = 0; i < oThreads.Length; i++) { /* * The different threads in 'oThreads' use the same * variable 'Counter.Count'. * => The variable 'Counter.Count' is shared by these threads. * * Without 'Join' the 'WriteLine' does his work before the * last thread is done. * => Total is less then 100.000. */ oThreads[i].Join(); } /* * Show to the console the total value of 'Counter.Count' *(after the 10 threads) * Should be 10 * 10.000 = 100.000 */ Console.WriteLine("Total: {0}", Counter.Count); Console.ReadLine(); } static void UpdateCount() { for (int i = 1; i <= 10000; ++i) { Counter.Count = Counter.Count + 1; } } } public class Counter { public static int Count; } } The expected 'Total' that is written to the console is '100.000' (10 threads that increment 'Counter.Count' with '10.000'). The book i'm currently reading (http://www.amazon.com/MCTS-Self-Paced-Training-Exam-70-536/dp/0735622779) says that if you run this code on a hyperthreading- or a multiprocessorsystem the 'Total' that is written to the console will sometimes be less than '100.000'. I don't understand the explanation.
-
Consider the following: namespace Lesson2 { class Program { static void Main(string[] args) { System.Threading.ThreadStart oThreadStart; oThreadStart = new System.Threading.ThreadStart(UpdateCount); System.Threading.Thread[] oThreads; oThreads = new System.Threading.Thread[10]; for (int i = 0; i < oThreads.Length; i++) { oThreads[i] = new System.Threading.Thread(oThreadStart); oThreads[i].Start(); } // Wait for them to complete for (int i = 0; i < oThreads.Length; i++) { /* * The different threads in 'oThreads' use the same * variable 'Counter.Count'. * => The variable 'Counter.Count' is shared by these threads. * * Without 'Join' the 'WriteLine' does his work before the * last thread is done. * => Total is less then 100.000. */ oThreads[i].Join(); } /* * Show to the console the total value of 'Counter.Count' *(after the 10 threads) * Should be 10 * 10.000 = 100.000 */ Console.WriteLine("Total: {0}", Counter.Count); Console.ReadLine(); } static void UpdateCount() { for (int i = 1; i <= 10000; ++i) { Counter.Count = Counter.Count + 1; } } } public class Counter { public static int Count; } } The expected 'Total' that is written to the console is '100.000' (10 threads that increment 'Counter.Count' with '10.000'). The book i'm currently reading (http://www.amazon.com/MCTS-Self-Paced-Training-Exam-70-536/dp/0735622779) says that if you run this code on a hyperthreading- or a multiprocessorsystem the 'Total' that is written to the console will sometimes be less than '100.000'. I don't understand the explanation.
The potential problem on a hyperthreaded or multi-processor PC is due to the fact that each processor in a PC maintains its own cache. Therefore, if any of the threads executing in your routine happen to run on a different processor, that processor updates its own cache and does not automatically publish the new value to the other processor. This would cause your counter to 'miss' that particular iteration of the counter. There are several potential solutions to get around this, for instance using the VolatileRead and VolatileWrite methods of the Thread class (these use shared memory that all processor's can access, rather than storing the value of your variable in a CPU register) or using the MemoryBarrier of the Thread class (this method flushes the caches and CPU registers of all the processors into memory, ensuring that variables contain current data). You can get plenty of info on the Thread class and it's methods on the MSDN website. Hope that helps.
-
The potential problem on a hyperthreaded or multi-processor PC is due to the fact that each processor in a PC maintains its own cache. Therefore, if any of the threads executing in your routine happen to run on a different processor, that processor updates its own cache and does not automatically publish the new value to the other processor. This would cause your counter to 'miss' that particular iteration of the counter. There are several potential solutions to get around this, for instance using the VolatileRead and VolatileWrite methods of the Thread class (these use shared memory that all processor's can access, rather than storing the value of your variable in a CPU register) or using the MemoryBarrier of the Thread class (this method flushes the caches and CPU registers of all the processors into memory, ensuring that variables contain current data). You can get plenty of info on the Thread class and it's methods on the MSDN website. Hope that helps.
Thx