英文:
Is it safe to call DispatchQueue sync for read operations?
问题
以下是代码部分的翻译:
public final class UserRegistry {
private var infoMap: [String: User] = [:]
private let queue: DispatchQueue = .init(label: "userRegistry.queue")
func register(_ user: User) {
queue.async { [weak self] in
self?.infoMap[user.id] = user
}
}
func deregister(_ user: User) {
queue.async { [weak self] in
self?.infoMap[user.id] = nil
}
}
func getUser(for id: String) -> User? {
queue.sync {
infoMap[id]
}
}
}
希望这对你有所帮助。如果有任何其他疑问,请随时提出。
英文:
I have a class that reads from and writes to a dictionary using a serial dispatch queue. While the write operations are asynchronous, the read operations are synchronous. I want to avoid the use of a completion handler for reading. Does this create any issues? The issue could range from deadlocks or crashes by calling from the main thread.
public final class UserRegistry {
private var infoMap: [String: User] = [:]
private let queue: DispatchQueue = .init(label: "userRegistry.queue")
func register(_ user: User) {
queue.async { [weak self] in
self?.infoMap[user.id] = user
}
}
func deregister(_ user: User) {
queue.async { [weak self] in
self?.infoMap[user.id] = nil
}
}
func getUser(for id: String) -> User? {
queue.sync {
infoMap[id]
}
}
}
I tried to create a completion handler and that would cause a series of changes at the call site across the code base. I expect that reading synchrnously should be safe regardless of which thread the consumer calls this from.
Read operation - func getUser(for id: String) -> User?
Write operations - func register(_ user: User)
& func deregister(_ user: User)
答案1
得分: 2
可以安全地在读取时使用 sync
,在写入时使用 async
,不会发生 infoMap
上的死锁或竞争。
甚至不一定需要使用 [weak self]
,因为捕获 self
的块不会存活很长时间。
你也可能不需要为写操作使用 async
。你可以只使用 sync
进行写操作。因为 infoMap
从不被复制,所以不会发生复制写入,而且它只会很少重新分配。因此,写操作几乎总是足够便宜,可以同步运行。
请记住,如果 User
是一个引用类型(或者以其他方式没有值语义),你仍然可能会发生涉及个别 User
对象的竞争。
英文:
Yes, you can safely use sync
for reads and async
for writes and there will not be any deadlocks or races on infoMap
.
You don't even particularly need to use [weak self]
, since the blocks capturing self
won't live long.
You also don't probably need to use async
for the writes. You could just use sync
for writes too. Because infoMap
is never copied, there won't be any copy-on-writes, and it will only be reallocated rarely. Thus the write operations should almost always be cheap enough to be run synchronously.
Keep in mind that if User
is a reference type (or otherwise doesn't have value semantics), you might still have races involving individual User
objects.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论