Semaphore Slim and Async
On this post I will focus on async waiting on Semaphore (using SemaphoreSlim).
In general .NET is having 2 Semaphore implementations:
– Semaphore which is the legacy implementation (but support cross process operations)
– SemaphoreSlim which is lightweight version. It bring some performance improvements but it don’t support cross process operation.
this post will focus on SemaphoreSlim WaitAsync API.
Let start analyzing the following code snippet, think what’s wrong with it:
In general the snippet is starting ExecAsyc 10 times, but after the 4th iteration
it will get blocked until one of the previous iteration will reach the finally section and release the semaphore.
In result “Keep working” (on line 9) will wait until the 10 iteration will pass (line 22)
Let’s think what would had happen if the blocked thread would be a thread pool’s thread rather the main thread?
On this case it would cause Thread Pool starvation, because the blocking thread won’t return to the Pool while waiting.
This starvation may damage the overall performance of your process .
For example think about services, both Web API and WCF is handling the incoming request on the Thread Pool.
The solution is simple and straight forward, the the following code snippet:
All you have to do is awaiting WaitAsync instead of blocking on Wait (line 5).
When speaking on Thread Pool the tread will return to the pool until the lock will be released.
Remember that Task by default will use Thread from the Thread Pool (default TaskScheduler).
WaitAsync is a small feature but it represent more general pattern. you should always
prefer awaiting on async operation rather blocking on synchronous operations.