C# Threading: a race condition example

c#, multithreading

Solution

I think the writer of the article has confused things.

VoteyDisciple is correct that `++i` is not atomic and a race condition can occur if the target is not locked during the operation but this will not cause the issue described above.

If a race condition occurs calling `++i` then internal operations of the `++` operator will look something like:-

- 1st thread reads value 0

- 2nd thread reads value 0

- 1st thread increments value to 1

- 2nd thread increments value to 1

- 1st thread writes value 1

- 2nd thread writes value 1

The order of operations 3 to 6 is unimportant, the point is that both the read operations, 1 and 2, can occur when the variable has value x resulting in the same incrementation to y, rather than each thread performing incrementations for distinct values of x and y.

This may result in the following output:-

First runner incrementing i from 0 to 1
Second runner incrementing i from 0 to 1

What would be even worse is the following:-

- 1st thread reads value 0

- 2nd thread reads value 0

- 2nd thread increments value to 1

- 2nd thread writes value 1

- 2nd thread reads value 1

- 2nd thread increments value to 2

- 2nd thread writes value 2

- 1st thread increments value to 1

- 1st thread writes value 1

- 2nd thread reads value 1

- 2nd thread increments value to 2

- 2nd thread writes value 2

This may result in the following output:-

First runner incrementing i from 0 to 1
Second runner incrementing i from 0 to 1
Second runner incrementing i from 1 to 2
Second runner incrementing i from 1 to 2

And so on.

Furthermore, there is a possible race condition between reading `i` and performing `++i` since the Console.WriteLine call concatenates `i` and `++i`. This may result in output like:-

First runner incrementing i from 0 to 1
Second runner incrementing i from 1 to 3
First runner incrementing i from 1 to 2

The jumbled console output which the writer has described can only result from the unpredictability of the console output and has nothing to do with a race condition on the `i` variable. Taking a lock on `i` whilst performing `++i` or whilst concatenating `i` and `++i` will not change this behaviour.

Problem

I am reading http://www.mono-project.com/ThreadsBeginnersGuide. The first example looks like this: ``` public class FirstUnsyncThreads { private int i = 0; public static void Main (string[] args) { FirstUnsyncThreads myThreads = new FirstUnsyncThreads (); } public FirstUnsyncThreads () { // Creating our two threads. The ThreadStart delegate is points to // the method being run in a new thread. Thread firstRunner = new Thread (new ThreadStart (this.firstRun)); Thread secondRunner = new Thread (new ThreadStart (this.secondRun)); // Starting our two threads. Thread.Sleep(10) gives the first Thread // 10 miliseconds more time. firstRunner.Start (); Thread.Sleep (10); secondRunner.Start (); } // This method is being excecuted on the first thread. public void firstRun () { while(this.i < 10) { Console.WriteLine ("First runner incrementing i from " + this.i + " to " + ++this.i); // This avoids that the first runner does all the work before // the second one has even started. (Happens on high performance // machines sometimes.) Thread.Sleep (100); } } // This method is being excecuted on the second thread. public void secondRun () { while(this.i < 10) { Console.WriteLine ("Second runner incrementing i from " + this.i + " to " + ++this.i); Thread.Sleep (100); } } } ``` Output: ``` First runner incrementing i from 0 to 1 Second runner incrementing i from 1 to 2 Second runner incrementing i from 3 to 4 First runner incrementing i from 2 to 3 Second runner incrementing i from 5 to 6 First runner incrementing i from 4 to 5 First runner incrementing i from 6 to 7 Second runner incrementing i from 7 to 8 Second runner incrementing i from 9 to 10 First runner incrementing i from 8 to 9 ``` Wow, what is this? Unfortunately, the explanation in the article is inadequate for me. Can you explain me why the increments happened in a jumbled order? Thanks!

Original source