When considering synchronization in an application, the decision truly depends on what the application and its worker threads are going to do. I would use synchronization if two or more threads could possibly manipulate the same instance of an object at the same time. An example of this in C# can be demonstrated through the use of storing data in a static object. A static object is initialized once per application and the data within the object can be accessed by all threads. I would use the synchronization primitives to prevent any data from being manipulated by multiple threads simultaneously. This would reduce any data corruption from occurring within the object. On the other hand if all the threads used non static objects and were independent of the other tasks there would be no need to use synchronization.
Synchronization Primitives in C#:
- Basic Blocking
- Non-Blocking Synchronization Constructs
The Basic Blocking methods include Sleep, Join, and Task.Wait. These methods force threads to wait until other threads have completed. In addition, these methods can also force a thread to wait a set amount of time before continuing to work.
The Locking primitive prevents a thread from entering a critical section of code while another thread is in the same critical section. If another thread attempts to enter a locked code, it will wait, until the code block is released.
The Signaling primitive allows a thread to temporarily pause work until receiving a notification from another thread that it is ok to continue working. The Signaling primitive removes the need for polling.
The Non-Blocking Synchronization Constructs protect access to a common field by calling upon processor primitives.