Firstly, I must say that I really appreciate your help in this matter. To hone my understanding, this is how I see it and please correct me if I am wrong.
If thread T1 was supposed to execute the wrong speculative loading path, the following lines of code will execute:
Thread T1 line 1: int someFieldValuePrefetched = lastValueSeen.SomeField; //prefetch speculatively Thread T1 line 2: if (this.m_value == lastValueSeen) { //speculation succeeded (accelerated case). The speculated read is used Thread T1 line 3: Console.WriteLine(someFieldValuePrefetched); } else { //speculation failed (slow case). The speculated read is discarded. ….. …. }
On the other hand, the T2 thread will need to execute the following lines of code.
Thread T2 line 1: old = m_value; Thread T2 line 2: m_value = new object(); Thread T2 line 3: old.SomeField = 1;
My first question is: what is vlue this.m_value when "Thread T1 line 1" is running? I suppose it is equal to the old m_ value before "Thread T2 line 2" was executed, right? Otherwise, the speculative branch did NOT choose an accelerated path. This leads me to ask if the T2 thread MUST also execute its lines of code out of order. That is, it performs "Thread T2 line 1", "Thread T2 line 3", "Thread T2 line 2", and not "Thread T2 line 1", "Thread T2 line 2", "Thread T2 line 3"? If so, then I believe the volatile keyword also prevents the T2 thread from executing code in order, right?
I see that the thread T1s "Thread T1 line 2" had to run after threads T2 "Thread T2 line 1" and "Thread T2 line 3" and before "Thread T2 line 2", then SomeField in thread T1 will be 1, although this it made no sense, as you noted, because when SomeField becomes 1, m_value is assigned a new value, which has a value of 0 for SomeField
Witl
source share