In my previous article, we started out with the concept of the threads. We discussed the use of multi-threaded environment to access resources, which requires us to understand the concept of thread safety. So in order to implement the thread safety, we need to implement some kind of mechanism which prevents/avoids two or more threads accessing the same resource at the same time.
So we have certain mechanisms in C#, which allows us to handle the situation. These mechanisms can be basically divided into different categories/scenarios, by which we can write thread safe code. I will only provide the types that can be used in different methods and will discuss them in detail in my future posts.
These scenarios include :
1. Blocking one or more threads until the current one finishes its execution :
- Thread.Sleep() : As the name specifies, it includes the use of Thread.Sleep method, to block the execution of the current thread for a specified interval of time. If we know that there is enough time after which the resource will be freed, we can block the current thread to wait till that time using this. The time specified here is in milliseconds.
- Thread.Join() : This mechanism causes the threads that are running to wait for the complete execution of the thread on which the Join() is applied For ex: We have 3 thread running. We apply Thread.Join() on the 3rd one, then the first two threads will not finish their execution until the join method is called on the 3rd one, i.e. the third thread blocks the execution of the complete process, until it finishes its execution.
2. Locking the resource to allow only one thread at a time to access it :
These are the most common and the better approaches to write the thread safe code. It simply includes applying some kind of lock on the resource when one of the thread wants to use it and releasing it as soon as it is done.
- lock : This includes the use of the lock keyword on the resource to be used, to allow only one resource at a time to access it
- Mutex : Mutex is similar to lock to block the contending resources but differs in the point that in Mutex, it can be applied across multiple processes. Multiple processes here implies that it can be used in two threads that are running in two different processes say Process A & B.
Also another difference is that Mutex is a bit slower then the corresponding locking process.
Semaphores – the thread manager :
There is another concept called the Semaphores which can be used to synchronize the execution of threads. Its basic concept is to create a pool with specific number of threads that are allowed to run under it. So in case there are more threads than the semaphore pool allows, then they have to wait until one of the thread finishes its execution.
For ex: An ATM machine booth may allow only 3 people at a time to enter. In case there are total of 10 people who want to withdraw their money, then the semaphore will allow only 3 people to enter the booth. Rest 7 of them will have to wait for exiting of any one from the inside. When one of them exits then, another one from the waiting 7 will enter the booth and start processing.
There is no order in which the 10 will enter the booth i.e. thread 1,2 and 5 may enter the booth first. When 1 or 2 finishes, then 8, 10 or any other may enter the booth and so on.
Apart from these discussed mechanisms, there are other ways also to manage the thread safety. In my further posts, I will try to discuss in detail about these especially the locks & the mutex. So till then enjoy reading and do let me know if you would like to add any point.