volatile
-
how come adding "volatile" in below code snippet didn't help? The output, without "volatile" would be like: m=1,000,000, n=999,993 My expectation was, m=n=1,000,000 exactly if I added "volatile".
using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace SimpleConsole { class Test { static int i = 0; static volatile int n = 0; static int m = 0; static Object SyncRoot = new Object(); static void Main(string[] args) { Task[] Tasks = new Task[100]; try { n = 0; m = 0; for (i = 0; i < 100; i++) { Task t = new Task( () => { for (int j = 0; j < 1000000; j++) { n++; // no lock lock (SyncRoot) { m++; } } } ); Tasks[i] = t; t.Start(); } Task.WaitAll(Tasks); Console.WriteLine("n=" + n + ", m=" + m); Console.WriteLine("Hit any key to exit"); Console.ReadLine(); } catch (Exception Ex) { Console.WriteLine("Error in main: " + Ex.Message); } return; } } }
dev
-
how come adding "volatile" in below code snippet didn't help? The output, without "volatile" would be like: m=1,000,000, n=999,993 My expectation was, m=n=1,000,000 exactly if I added "volatile".
using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace SimpleConsole { class Test { static int i = 0; static volatile int n = 0; static int m = 0; static Object SyncRoot = new Object(); static void Main(string[] args) { Task[] Tasks = new Task[100]; try { n = 0; m = 0; for (i = 0; i < 100; i++) { Task t = new Task( () => { for (int j = 0; j < 1000000; j++) { n++; // no lock lock (SyncRoot) { m++; } } } ); Tasks[i] = t; t.Start(); } Task.WaitAll(Tasks); Console.WriteLine("n=" + n + ", m=" + m); Console.WriteLine("Hit any key to exit"); Console.ReadLine(); } catch (Exception Ex) { Console.WriteLine("Error in main: " + Ex.Message); } return; } } }
dev
volatile
won't help that - all it does is signal to the compiler that it may be changed outside so it can't optimise it into a local register. That is not the same as locking the value. Don't forget, "n++" is just a syntactic sugar for "Fetch the value of 'n'. Add one to the value. Save the value back to 'n'" Without locking, other threads can get in between the "Fetch" and the "Save" and do what they like to the value of 'n' without affecting the actual value used by your code because once it is fetched the changes will be ignored.The only instant messaging I do involves my middle finger. English doesn't borrow from other languages. English follows other languages down dark alleys, knocks them over and goes through their pockets for loose grammar.
-
how come adding "volatile" in below code snippet didn't help? The output, without "volatile" would be like: m=1,000,000, n=999,993 My expectation was, m=n=1,000,000 exactly if I added "volatile".
using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace SimpleConsole { class Test { static int i = 0; static volatile int n = 0; static int m = 0; static Object SyncRoot = new Object(); static void Main(string[] args) { Task[] Tasks = new Task[100]; try { n = 0; m = 0; for (i = 0; i < 100; i++) { Task t = new Task( () => { for (int j = 0; j < 1000000; j++) { n++; // no lock lock (SyncRoot) { m++; } } } ); Tasks[i] = t; t.Start(); } Task.WaitAll(Tasks); Console.WriteLine("n=" + n + ", m=" + m); Console.WriteLine("Hit any key to exit"); Console.ReadLine(); } catch (Exception Ex) { Console.WriteLine("Error in main: " + Ex.Message); } return; } } }
dev
Try using the Interlocked.Increment method[^].
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer