Thread Safety In C#

Introduction

Thread safety is a concept applicable in the context of multi-threaded programs. Multiple thread can access to the same address space at the same time. So, they can write to the exact same memory location at the same time. It is a defining property of threads. So, this property of thread is not good for the functionality.
 
So, Thread safety is a technique which manipulates shared data structure in a manner that guarantees the safe execution of a piece of code by the multiple threads at the same time. A code is called thread safe if it is being called from multiple threads concurrently without the breaking of functionalities.
Thread safety removes the following conditions in the code:
  1. Race Condition
  2. Deadlocks

Race Condition

It is also called race hazard. It is a behavior of software or system where output is based on the sequence or timing of other uncontrolled events. It becomes painful or bug when events do not happen in the order in which functionality is required.

Race condition occurs when two threads access a shared variable at the same time. The first thread reads the variable, and the second thread writes to the same variable at the same time.
 
Symptoms of Race Condition
 
The most common symptom of a race condition is unexpected values of variable that are shared between multiple threads. In this case, sometimes one thread wins, and sometimes the other thread wins. At the other times, the result of execution may be correct. Also, if each thread executes separately, the result of variable comes expected.
 
Example:
 
Let us have two threads - Thread1 and Thread2 and both run simultaneously and lock has been not applied then result will be wrong.
This situation happened because locks were not applied and race condition happened.
  1. Int myValue = 0;  
  2. Thread1 ---Reads value-------> 0  
  3. Thread2 --Reads Value--------> 0  
  4. Thread1 --Increases value with one and writes back----> 0 +1  
  5. Same time,  
  6. Thread2 --Increases value with one and writes back ------> 0+1  
  7. Final Result = 1  
  8. Expected Result = 2  
This situation happened because locks were not applied and race condition happened. 
 
Avoid Race Condition:
 
Best approach to handle race condition is to write code very carefully and proactively. Always try to use locks, mutexes, ManualResetEvents, etc to make code thread safe in the case of multi-threaded environment.

Deadlock

Deadlock case happens in concurrent or multi-threaded environment. It is kind of a situation in which two or more competing threads or tasks wait for the other task to finish and they never finish.
 
It is a vary famous problem in multi processing systems, parallel computing and distributed systems. This case basically happens with the shared resource. This resource locks in this case. Deadlock has very vast explanation.
 
Conditions of Deadlock
 
A condition is called Deadlock if the following condition matches:
  1. Mutual Exclusion: Only process can use the resource at the given time.
  2. Hold and Wait
  3. No Preemption
  4. Circular Wait
These four conditions are know as the Coffman Conditions. Edward G. Coffman, Jr. described this in his article published in 1971.

Ways to Make an Object Thread-Safe

The following are the three approaches to make an object thread-safe:
  1. Synchronize the critical section.
  2. Make it immutable
  3. Use a thread-safe wrapper

Questions based on Thread-Safety

Question: Is the C# Static Constructor Thread -Safe?
 
Static constructors are guaranteed to be run only once per application domain, before any instances of a class are created or any static members are accessed.
 
Using a Static Constructor actually is Thread-Safe.
 
Question: Is C# Static Method Thread-Safe?
 
Static methods are not inherently thread-safe. CLR of C# doesn't thread different than instance method.
 
Question: Is C# Delegate Thread-Safe?
 
Modifying event is not thread-safe, but invoking a Delegate is thread-safe. Since a Delegate is immutable type so it is thread safe.