Assignments and Uses in Multithreaded Environments
-
Hello -- I am looking for information about the guarantees that .NET makes about assignments completing in a multithreading environment. Specifically, consider the following program that asynchronously finds small factors of integers. The code has been intentionally structured in a slightly peculiar way in order to help make the question clear, and is not necessarily otherwise robust. The question is: what guarantee, if any, does .NET make about the assignment labeled "ASSIGNMENT (1)" completing before the result of the assignment is first referenced in the function "findFactor"? For example, how do we know that the value of d_n isn't in a cache somewhere waiting to be written to memory before findFactor accesses an old value of d_n, or that the compiler hasn't decided to do some instruction reordering so that the completion of the assignment of d_n happens to be delayed until after d_n is referenced in "findFactor"? Similarly, how do we know (or is it even guaranteed) that the assignment labeled "ASSIGNMENT (2)" has completed before the assigned variable is referenced in the Factor property?
using System; using System.Threading; /* Asynchronously find the smallest nontrivial factor of a positive integer, using brute force. */ class Factorer { public Factorer() { d_n = 0; d_completed = false; d_worker = null; d_asr = null; } public void BeginWork(int n) { if (n < 2) throw new ApplicationException("n must be an integer greater than 1"); d_completed = false; d_worker = new WorkFunc(findFactor); d_n = n; // ASSIGNMENT (1) d_asr = d_worker.BeginInvoke(null,null); } public bool Completed { get { if ((! d_completed) && d_asr.IsCompleted) { d_worker.EndInvoke(d_asr); d_completed = true; } return d_completed; } } /* Return 0 if n is prime; otherwise return a positive integer that is the smallest factor of n. */ public int Factor { get { if (! Completed) { throw new ApplicationException ("Cannot get result before work is complete."); } return d_factor; } } int d_n; int d_factor; WorkFunc d_worker; IAsyncResult d_asr; bool d_completed; delegate void WorkFunc(); void findFactor() { int n = d_n; if (n == 2) { d_factor = 0; return; } int u = (int) Math.Sqrt(n); for (int i = 2; i <= u; i++) { if ((n % i