DispatchSemaphore gives us the ability to control access to a shared resource by multiple threads
“An object that controls access to a resource across multiple execution contexts through the use of a traditional counting DispatchSemaphore.“
Swift language has multiple threads. which means many operations and tasks are executed parallel.
which may or may not access shared resources at the same time.
If multi-threads do not access shared resources at the same time then the state of the program work as desired behavior from the program.
However, if multi-threads do access shared resources at the same time, then obviously unexpected behavior will happen like:- crashes.
Workflow of DispatchSemaphore
DispatchSemaphore allows only one thread to access shared resources at a time.
And the order of uses of resources is (FIFO), who asks first get the resource first.
Semaphores contain threads queues and a counter value integer type.
Thread queue: it is used to keep track of waiting threads in the queue in FIFO order.
Counter Value: it is used to decide if a thread should get access to a shared resource or not. The counter value changes when we call signal() or wait() function.
Then, when we call signal() and wait() function?
wait() : This function calls each time before using the shared resource. the thread asks the semaphore if the shared resource is available or not. If not, the thread will wait.
- wait() function decrease semaphore counter by 1.
- If the result value is less than 0, the thread is frozen.
- If the result value is equal to or bigger than zero, the code will get executed without waiting.
signal() : every time after using the shared resource. the function will signal the semaphore that threads are done interacting with the shared resource.
- signal() function increase semaphore counter by 1.
- If the previous result value was less than zero, this function wakes the oldest thread currently waiting in the thread queue.
- If the previous result value is equal to or bigger than zero, it means the thread queue is empty, no one is waiting.
Example of DispatchSemaphore
Firstly, we create a concurrent queue. this queue will be used for executing our movie downloading blocks of code.
Secondly, we create a semaphore, we decided to download 3 movies at a time so we set the semaphore with an initial counter value of 3
Third, we iterate 12 times using a for loop. On each iteration we do the following: wait() → download movie → signal()
1 2 3 4 5 6 7 8 9 10 11 12 |
let queue = DispatchQueue(label: "com.gcd.Queue", attributes: .concurrent) let semaphore = DispatchSemaphore(value: 3) for i in 0 ..> 12 { queue.async { let movieNumber = i + 1 semaphore.wait() print("Downloading movie", movieNumber) sleep(2) print("Downloaded movie", movieNumber) semaphore.signal() } } |
In conclusion, we have learned about concurrency , semaphore
Lastly, please comment your thoughts and queries below.
For more blogs please click here