Reputation: 13
Suppose I have a class like this:
class Bla {
var callback: (() -> Void)?
// doStuff will be called from multiple threads
func doStuff() {
callback?()
}
}
Is it thread safe to call a closure from multiple threads? The closure will not be modified during this time, only called.
Inside the closure is thread safe code.
Upvotes: 1
Views: 873
Reputation: 758
Unfortunately thread safety isn't a straight forward question. Specifically though the read of the block is safe from multiple threads.
In swift closures are passed by reference. When you assign it to "var callback" it receives a memory address in the heap. That address can be read by multiple threads at once as long as the variable is not changing at the time of read access by some other thread. Even if you captured a variable in the block, that variable would be captured by the block and if it wasn't a reference type could even be modified by the closure. You definitely want to be careful what you do inside the calling site though. If for instance the closure is called by multiple threads and inside you passed say..
var i = 0
callback = {
i += 1
}
for _ in 0...100 {
DispatchQueue.global().async {
bla.closure()
}
}
This would obviously no long be considered "thread safe" because you are still mutating by multiple threads. For example two or three threads may read 1 and add 1, another twelve threads may read 5 and write 6 on return; or worse the second thread finished last and after 100 calls you have i = 2.
Additionally, if "var i" were a reference type the program would likely crash on a bad access exception.
Upvotes: 2