iOS下线程安全的API请求时长计算方案咨询
并发安全的API请求时长计算实现
首先要明确:你当前的代码其实不存在并发问题——startDate是performRequest函数的局部变量,每次调用该函数都会创建一个独立的Date实例,并发请求之间的startDate完全隔离,不会互相覆盖或修改。
不过如果后续需要将计算出的时长写入共享资源(比如全局统计字典、数据库),这时候才需要处理线程安全问题。以下是两种可靠的实现方案:
方案一:局部变量隔离+串行队列处理共享资源
如果只是计算单请求时长,原逻辑足够;若要统计到共享容器,用串行队列确保原子操作:
// 全局串行队列,用于处理共享资源的写入 private let statsQueue = DispatchQueue(label: "com.yourdomain.requestStats") // 共享统计字典,记录每个请求的时长 private var requestDurations: [String: TimeInterval] = [:] func performRequest(request: URLRequest) { let startDate = Date() let requestIdentifier = request.url?.absoluteString ?? UUID().uuidString let task = URLSession.shared.dataTask(with: request) { [weak self] data, response, error in guard let self = self else { return } let duration = Date().timeIntervalSince(startDate) print("请求时长:\(duration)s") // 串行队列确保共享资源的线程安全写入 self.statsQueue.sync { self.requestDurations[requestIdentifier] = duration } } task.resume() }
方案二:锁机制保护共享资源
如果更习惯用锁,可通过NSLock实现:
import Foundation private let durationLock = NSLock() private var requestDurations: [String: TimeInterval] = [:] func performRequest(request: URLRequest) { let startDate = Date() let requestID = request.url?.absoluteString ?? UUID().uuidString let task = URLSession.shared.dataTask(with: request) { data, response, error in let duration = Date().timeIntervalSince(startDate) // 加锁后操作共享字典 durationLock.lock() requestDurations[requestID] = duration durationLock.unlock() print("请求\(requestID)时长:\(duration)s") } task.resume() }
关键注意点
- 局部变量天然具备线程隔离性,无需额外同步;只有操作跨线程共享的资源时才需要线程安全处理。
- URLSession的回调默认在后台线程执行,若要更新UI,需切换到主线程:
DispatchQueue.main.async { // 更新UI操作 }
内容的提问来源于stack exchange,提问作者Anastasia Veremiichyk
相关产品推荐
相关产品推荐

