我已经阅读了有关此主题的其他SO帖子,并观看了WWDC 2016关于通过GCD同步子系统的演讲。见:〜@ 11.30标记。
https://developer.apple.com/videos/play/wwdc2016/720/
在这项研究之后,我仍然对最佳实践感到困惑。我想指导以下代码是否是确保Swift中Singleton访问器的线程安全的适当方法。
在下面的示例代码中,单例(ResourceManager)有两个主要任务:
1)给定一个resourceID和一个闭包,通过该闭包提供相应的资源。如果所需的资源已经在私有缓存中,请使用它,否则,需要异步创建资源,并在主线程上输出。
2)给定一个resourceID,告诉调用者相应的Resource是否在私有缓存中。
在以下代码中,这是通过专用的串行GCD队列实现的。
self._queue.async {
let maybeResource = Resource(resourceID: resourceID)
self._queue.sync {
if let resource = maybeResource {
self._resourcesDict[resourceID] = resource
}
DispatchQueue.main.async {
completionHandler(maybeResource)
}
}
}
问题
#1,#2和#3的机制是否足以确保访问的安全性?您可以通过这些方法看到任何问题吗?
机制#2是否正确?或者我应该使用_queue.sync设置缓存,如下所示:
resource(::)
感谢您的帮助。
[编辑 - 修改// Revised at point #1 to do checking within sync
func resource(forResourceID resourceID: ResourceID,
completionHandler: @escaping (Resource?) -> ())
{
// #1. REVISED. Do Resource checking within sync.
// Resource already in the cache? Use that, job is done.
self._queue.sync {
if let resource = self._resourcesDict[resourceID] {
DispatchQueue.main.async {
completionHandler(resource)
}
}
return
}
// #2.
// Resource is not in the cache, so load it asynchronously.
self._queue.async {
let maybeResource = Resource(resourceID: resourceID)
DispatchQueue.main.async {
if let resource = maybeResource {
self._resourcesDict[resourceID] = resource
}
completionHandler(maybeResource)
}
}
}
方法,根据迈克的建议]
{{1}}