I current have a set of asynchronous functions that are both called in the viewDidLoad()
. At the end of each function is a bool that is set from false to true upon completion of the function. There is also a conditional statement checking both function's bools that fires a third function. This conditional statement is in both functions (that I want called when both of the two have finished). Generally:
var checkOne = false
var checkTwo = false
func functionOne(){
//async stuff
checkOne = true
if checkOne == true && checkTwo == true{
functionThree()//will only run if both functionOne and functionTwo have been completed
}
}
func functionTwo(){
//async stuff
checkTwo = true
if checkOne == true && checkTwo == true{
functionThree()//will only run if both functionOne and functionTwo have been completed
}
}
func functionThree(){
//stuff
}
override func viewDidLoad() {
functionOne()
functionTwo()
}
This setup ensures that functionThree()
can only be run when both functionOne
and functionTwo
are done. If functionOne
finishes its async stuff before functionTwo()
and gets to the conditional to fire functionThree()
, it will not do it as checkTwo
has not been made true yet. Thus, when functionTwo()
's async stuff is done, it will fire functionThree()
. This works appropriately and has not caused an issue once. What I want to expressly avoid, though, is the async functions happening to finish, and therefore calling functionThree()
, at the exact same time. To do this I would like to set an NSLock()
, but, despite looking up documentation, I have zero clue how to do this as I need the same lock being handled by two different functions. Anyone have any ideas?
An
NSLock
is a mutex; it prevents multiple threads from accessing the same resource simultaneously, which is exactly what you want to do here. Once one thread acquires the lock, other threads attempting to acquire the lock will wait until the first thread releases the lock.You'll want to create a lock and store it somewhere that persists across and between function calls, most likely in an instance variable in this case. To acquire the lock, call its
lock
method, and to release it, useunlock
:A more "modern" approach is to use a
DispatchQueue
instead of anNSLock
. Dispatch is higher-level than APIs like NSLock and NSThread; instead of directly working with locks and threads, you'll use queues.A serial dispatch queue works like a checkout line at a store. You submit blocks of code to the queue, and it executes them one at a time in the order they were received. You can also create a concurrent dispatch queue which executes its tasks simultaneously by passing
.concurrent
to theoptions
parameter of theDispatchQueue
initializer.A serial dispatch queue is an easy way to protect a resource from being accessed by multiple threads at once -- just create a queue for that resource, and put every access to that resource on the queue.