I seem to have a classic solution for Readers-Writers problem in Swift using concurrent DispatchQueue with a barrier for writes. However, then I run my test code, it deadlocks.
Here's my wanna-be-thread-safe data structure:
class Container<T> {
private var _value: T
private let _queue = DispatchQueue(label: "containerQueue", attributes: .concurrent)
init(_ value: T) {
self._value = value
}
var value: T {
get {
_queue.sync {
_value
}
}
set {
_queue.async(flags: .barrier) {
self._value = newValue
}
}
}
}
And here's my test code:
class ContainerTest {
let testQueue = DispatchQueue(label: "testQueue", attributes: .concurrent)
var container = Container(0)
let group = DispatchGroup()
func runTest() {
for i in 0..<1000 {
testQueue.async(group: group) {
self.container.value = max(i, self.container.value)
}
}
group.notify(queue: .main) {
print("Finished")
}
}
}
The piece of code that's run repeatedly is just some random read and write operations. It's not attempting to produce anything sensible, it's just there to stress-test the data structure.
So when I run this, "Finished" is never printed. However, if I change _queue.async(flags: .barrier)
to _queue.sync(flags: .barrier)
, then I see "Finished" printed.
I'm guessing when I'm using the async
write version, I'm getting a deadlock, but why? It's the textbook Readers-Writers solution that's typically used. Perhaps it's my test code that is at fault, but again, why?