In c# we have a multiple ways to avoid a race condition determined by the type of an application we are used. Generally we use a following two common methods that works in any condition:
1. Wait Handles
2. Signaling
Example:
Let's take an example, we have two threads says t1,t2. These threads trying to access a shared variable y. Both of these two threads simultaneously need to read data from a variable y and then try to modify the data on the variable y. In this situation, value of shared variable will be the last written value of the thread. In this example we want that the first thread will execute in last and writes the value to the variable x.
To do this we start all the threads at the same time and enforced the first thread to wait until the second and thirds threads will not give a signal that they complete their work. In the same way we need to enforce the main thread to wait until the first threads completes its work. It means that the Console.WriteLine() is not execute before the other threads complete their work.
Code:
using System;
using System.Threading;
namespace RaceConditionSolution
{
class RaceConditionSolutionProgram
{
int x = 0;
AutoResetEvent threadEvent1 = new AutoResetEvent(false);
AutoResetEvent threadEvent2 = new AutoResetEvent(false);
AutoResetEvent threadEvent3 = new AutoResetEvent(false);
void thread1()
{
WaitHandle.WaitAll(new WaitHandle[] { threadEvent2 , threadEvent3});
x = 1;
threadEvent1.Set();
}
void thread2() { x = 2; threadEvent2.Set(); }
void thread3() { x = 3; threadEvent3.Set(); }
static void Main(string[] args)
{
RaceConditionSolutionProgram rcs = new RaceConditionSolutionProgram();
Thread threads1 = new Thread(rcs.thread1);
Thread threads2 = new Thread(rcs.thread2);
Thread threads3 = new Thread(rcs.thread3);
WaitHandle[] waitHandles = new WaitHandle[] { rcs.threadEvent2, rcs.threadEvent3};
threads1.Start();
threads2.Start();
threads3.Start();
WaitHandle.WaitAny(new WaitHandle[] { rcs.threadEvent1});
Console.WriteLine(rcs.x);
Console.Read();
}
}
}
Output:
In above code we have used a AutoResetEvent for each thread, when a threads finish their work then they will call their set() method to give a signals to their respective AutoResetEvent. The first thread will waits for the signal of the second and third thread, after getting a signal it will starts its execution. In the same way main thread will waits for the first thread signal before printing the value of x variable. And finally, we will always ensure that the final value of x is 1.
0 Comment(s)