C# ThreadStatic + volatile members not working as expected C# ThreadStatic + volatile members not working as expected multithreading multithreading

C# ThreadStatic + volatile members not working as expected


Threads are executing at the same time. What conceptually happens is this:

staticVolatileTestString += Environment.NewLine + "\tthread " + ((int) o) + " setting threadInt to " + newVal;
  1. Thread 1 reads staticVolatileTestString
  2. Thread 2 reads staticVolatileTestString
  3. Thread 3 reads staticVolatileTestString
  4. Thread 1 appends the stuff and writes staticVolatileTestString back
  5. Thread 2 appends the stuff and writes staticVolatileTestString back
  6. Thread 3 appends the stuff and writes staticVolatileTestString back

That causes your lines to be lost. Volatile doesn't help here; the whole process of concatenating the string is not atomic. You need to use a lock around those operations:

private static object sync = new object();lock (sync) {    staticVolatileTestString += Environment.NewLine + "\tthread " + ((int) o) + " setting threadInt to " + newVal;}


The MSDN describes what the keyword volatile does here:

The volatile keyword indicates that a field might be modified by multiple concurrently executing threads. Fields that are declared volatile are not subject to compiler optimizations that assume access by a single thread. This ensures that the most up-to-date value is present in the field at all times.

This means, in your example, what happens is about this (this can vary from time to time; depends on the scheduler):

  • thread 0 is reading the string out of staticVolatileTestString
  • thread 0 is appending 'thread 0 setting threadInt to 88'
  • thread 0 is writing the string back into staticVolatileTestString

this is like expected so far, but then:

  • thread 1-4 are reading the string out of staticVolatileTestString
  • thread 1 is appending 'thread 1 setting threadInt to 97'
  • thread 2 is appending 'thread 2 setting threadInt to 11'
  • thread 2 is writing the string back into staticVolatileTestString
  • ... threads 1, 2, 3 are reading and appending, and writing
  • thread 4 is writing the string back into staticVolatileTestString
  • and so on...

see what happened here? thread 4 read the string 'thread 0 setting threadInt to 88', appended its 'thread 4...' and wrote it back, overwriting everything thread 1, 2 and 3 had written into the string already.