这里有一个非常虚拟和简单化的问题版本:
独生子
class Singleton { static var shared = Singleton() var foo: String = "foo"}
单例的使用(为简单起见,来自AppDelegate)
class AppDelegate: UIResponder,UIApplicationDelegate { var window: UIWindow? func application(_ application: UIApplication,dIDFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { // OverrIDe point for customization after application launch. dispatchQueue.global().async { var foo = Singleton.shared.foo // Causes data race } dispatchQueue.global().async { Singleton.shared.foo = "bar" // Causes data race } return true }}
有没有办法确保单例是线程安全的,所以它可以在应用程序的任何地方使用,而不必担心你在哪个线程?
这个问题不是Using a dispatch_once singleton model in Swift的重复(因为我理解正确),因为它们正在解决访问单例对象本身的问题,但不能确保其属性的读取和写入是安全地完成的.
感谢@rmaddy的评论指出了我正确的方向,我能够解决问题.为了使Singleton线程的属性foo安全,需要修改如下:
class Singleton { static var shared = Singleton() private let internalQueue = dispatchQueue(label: "SingletionInternalQueue",qos: .default,attributes: .concurrent) private var _foo: String = "aaa" var foo: String { get { return internalQueue.sync { _foo } } set (newState) { internalQueue.async(flags: .barrIEr) { self._foo = newState } } } func setup(string: String) { foo = string }}
线程安全是通过使用计算属性foo来完成的,该属性使用internalQueue来访问“real”_foo属性.
此外,为了获得更好的性能,internalQueue被创建为并发.这意味着在写入属性时需要添加barrIEr标志.
屏障标志的作用是确保在队列中所有先前计划的工作项完成时执行工作项.
总结以上是内存溢出为你收集整理的swift中的线程安全单例全部内容,希望文章能够帮你解决swift中的线程安全单例所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)