However, when multiple threads are thrown into the mix, you can easily have situations in which the processor switches to another thread while your object is in an invalid state. If that thread then also attempts to use this same object, the results can be quite unpredictable. Therefore, the term "thread safety" means that the members of an object always maintain a valid state when used concurrently by multiple threads.
So, how do we prevent this unpredictable state? Actually, as is common in programming, there are several ways to address this well-known issue. In this section, I'll cover the most common means: synchronization. Through synchronization, you specify critical sections of code that can be entered by only one thread at a time, thereby guaranteeing that any temporary invalid states of your object are not seen by the object's clients.
We'll be looking at several means of defining critical sections, including the .NET Monitor and Mutex classes as well as the C# lock statement.