Swift - 使用GCD的Singleton Accessor线程安全

时间:2017-06-15 05:35:10

标签: ios swift multithreading singleton grand-central-dispatch

我已经阅读了有关此主题的其他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}}

0 个答案:

没有答案