Created
June 25, 2012 04:23
-
-
Save AArnott/2986510 to your computer and use it in GitHub Desktop.
Demonstrates how the memory model in .NET requires the use of volatile fields when not using locks.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Threading; | |
namespace MemoryModelTest { | |
class Program { | |
static Barrier barrier; | |
static volatile LazyExample example; | |
static bool exit; | |
static volatile CountdownEvent evt; | |
static void Main(string[] args) { | |
var threads = new Thread[Environment.ProcessorCount]; | |
barrier = new Barrier(threads.Length + 1); | |
for (int i = 0; i < threads.Length; i++) { | |
threads[i] = new Thread(ThreadWorker); | |
threads[i].Start(); | |
} | |
while (true) { | |
evt = new CountdownEvent(threads.Length); | |
example = new LazyExample(); | |
barrier.SignalAndWait(); | |
evt.Wait(); | |
} | |
//Console.ReadLine(); | |
//exit = true; | |
//for (int i = 0; i < threads.Length; i++) { | |
// threads[i].Join(); | |
//} | |
} | |
static void ThreadWorker() { | |
while (!exit) { | |
barrier.SignalAndWait(); | |
int value = example.GetInt(); | |
if (value != 42) { | |
Console.WriteLine("Iteration {0} obtained unexpected value {1}", barrier.CurrentPhaseNumber, value); | |
} | |
evt.Signal(); | |
} | |
} | |
} | |
// WARNING: Bad code | |
class LazyExample { | |
private int _value; | |
private bool _initialized; // fix the bug in this code by adding volatile to this field. | |
public int GetInt() { | |
if (_value < 0) throw new Exception(); // NOTE: extra reads to get _value | |
// pre-loaded into a register | |
if (!_initialized) // Read 1 | |
{ | |
_value = 42; | |
_initialized = true; | |
return _value; // This extra return also happens to be needed | |
// to demo the behavior in .NET 4.5. | |
} | |
return _value; // Read 2 | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment