This time, Joe Developer thinks he found a bug in the .NET framework. Joe read that the volatile modifier is "usually used for a field that is accessed by multiple threads without using the lock Statement". Joe wants to try this out, and writes the following class.
class Worker
{
public void Start()
{
queue = new Queue<string>();
Thread[] threads = new Thread[maxThreads];
for (int i = 0; i < threads.Length; i++)
threads[i] = new Thread(PopulateQueue);
Array.ForEach(threads, delegate(Thread t) { t.Start(); });
Array.ForEach(threads, delegate(Thread t) { t.Join(); });
Debug.Assert(queue.Count == maxThreads * maxIterations);
}
void PopulateQueue()
{
for (int i = 0; i < maxIterations; i++)
{
queue.Enqueue("foo");
}
}
volatile Queue<string> queue;
const int maxThreads = 5;
const int maxIterations = 1000000;
}
This code ran successfully at least a dozen times, then suddenly blew up with the following exception:
System.ArgumentException was unhandled
Message="Destination array was not long enough.
Check destIndex and length, and the array's lower bounds."
Source="mscorlib"
ParamName=""
StackTrace:
at System.Array.Copy ...
at System.Collections.Generic.Queue`1.SetCapacity ...
at System.Collections.Generic.Queue`1.Enqueue ...
at Worker.PopulateQueue ...
...
Joe thinks something has gone terribly wrong in the CLR, and for once, Joe would like to show his boss a problem in someone else's software. What should his boss think?