ios - 使用调度组时如何使公共资源线程安全?
问题描述
我有一个用户类,每次用户打开应用程序时都需要更新
class User : NSObject, NSCoding {
var vehicles : [Vehicles]
var bankaccounts : [BankAccounts]
var friends : [Friends]
}
在我的主屏幕 ViewController 中,我有一个使用 3 个 Alamofire 请求从后端获取数据的函数。最后,我将数据保存在 UserDefaults 中。DispatchGroup 是我首先想到的实现这一点。这是代码
func loadUserData {
var user = User()
let userDataDispatchGroup = DispatchGroup()
userDataDispatchGroup.enter()
AF.request(...).responseJSON {
//update the user.vehicles array
userDataDispatchGroup.leave()
}
userDataDispatchGroup.enter()
AF.request(...).responseJSON {
//update the user.bankaccounts array
userDataDispatchGroup.leave()
}
userDataDispatchGroup.enter()
AF.request(...).responseJSON {
//update the user.friends array
userDataDispatchGroup.leave()
}
userDataDispatchGroup.notify(queue: .main) {
let encodedData = NSKeyedArchiver.archivedData(withRootObject: user)
UserDefaults.standard.set(encodedData, forKey: "user")
}
}
但我不清楚我的用户对象的线程安全性。由于它将在三个不同的回调中更新,线程安全在这里会是一个问题吗?如果是,解决问题的最佳方法是什么?我正在考虑使用 DispatchSemaphore。但我不确定这是否是正确的方法。
解决方案
您问:
但我不清楚我的用户对象的线程安全性。由于它将在三个不同的回调中更新,线程安全在这里会是一个问题吗?
您的代码片段中没有线程安全问题,因为 Alamofire 在主线程上调用其完成处理程序。他们这样做是为了帮助减轻多线程问题。DispatchQueue.main.async
在这种情况下不需要任何东西。正如 Alamofire文档所说:
默认情况下,传递给响应处理程序的闭包在队列上执行,但可以传递
.main
特定的闭包来执行闭包。DispatchQueue
因此,除非您做了一些不寻常的事情(例如.main
用一些并发覆盖默认队列DispatchQueue
),否则 Alamofire 将在主线程上运行其完成处理程序,从而减轻线程安全问题。
如果您使用的是不同的 API,它没有在主线程上URLSession.shared
调用其完成处理程序(例如,在后台队列上调用其完成处理程序),那么可能会有问题,但 Alamofire 不会。(甚至URLSession
使用串行后台队列,因此使用您的模式不会有问题,您正在更新局部变量。)
最重要的是,只要您不同时从多个线程更改/访问变量,线程安全问题就会大大减轻。
推荐阅读
- r - 不能在 sparklyr tbl 上的 dplyr mutate 函数中使用 grepl
- windows - 显示名称证书 OID - Windows
- c++ - Why does
prevent the use of "si_" as prefix for the name of some variables? - python - 为我的 for 循环的每次迭代创建唯一的 CSV
- c - C中的Sigaction处理程序
- bash - 从 bash 脚本中将带引号的字符串参数传递给 awk
- android - 如何为 RecyclerView 适配器设置监听器?
- angular6 - 修复 Internet Explorer 11 + Angular 6+ 项目中的语法错误
- javascript - 未捕获的类型错误:无法读取未定义的属性“ReactDebugCurrentFrame”
- docker - Docker swarm leave --force - 超出上下文截止日期