Swift - 检查弱变量是不是为 nil 或不是线程安全的?
Posted
技术标签:
【中文标题】Swift - 检查弱变量是不是为 nil 或不是线程安全的?【英文标题】:Swift - Is checking whether a weak variable is nil or not thread-safe?Swift - 检查弱变量是否为 nil 或不是线程安全的? 【发布时间】:2019-07-18 15:47:24 【问题描述】:我有一个运行很长时间的进程,我希望能够中断它。
func longProcess (shouldAbort: @escaping ()->Bool)
// Runs a long loop and periodically checks shouldAbort(),
// returning early if shouldAbort() returns true
这是我的班级使用它:
class Example
private var abortFlag: NSObject? = .init()
private var dispatchQueue: DispatchQueue = .init(label: "Example")
func startProcess ()
let shouldAbort: ()->Bool = [weak abortFlag] in
return abortFlag == nil
dispatchQueue.async
longProcess(shouldAbort: shouldAbort)
func abortProcess ()
self.abortFlag = nil
shouldAbort
闭包捕获对abortFlag
的weak
引用,并检查该引用是指向nil
还是指向NSObject
。由于引用是weak
,如果原来的NSObject
被释放,那么闭包捕获的引用将突然变为nil
,闭包将开始返回true
。闭包将在 longProcess
函数期间重复调用,这发生在私有 dispatchQueue
上。 Example
类的 abortProcess
方法将从其他队列外部调用。如果有人调用abortProcess()
,从而释放abortFlag
,同时longProcess
正试图执行检查以查看abortFlag
是否已被释放呢?检查myWeakReference == nil
是线程安全操作吗?
【问题讨论】:
你为什么首先使用这个虚拟的NSObject
实例?看起来布尔值也一样。
忽略我的回答。这实际上是正确的(也很有趣),但 Rob 的建议更好。只是不要这样做。
我同意 Rob 的建议是可行的方法,这就是我支持它的原因,但我的问题只是部分出于需求,另一部分是好奇心。你直接回答了我的问题,所以你的答案是正确的。我很高兴阅读了 Rob 的答案,并且它作为这篇文章的一部分存在供其他人阅读
【参考方案1】:
您可以将分派任务创建为DispatchWorkItem
,它已经具有线程安全的isCancelled
属性。然后,您可以将该DispatchWorkItem
分派到一个队列并让它定期检查它的isCancelled
。然后,您可以只 cancel
调度您想要停止它的点。
或者,当尝试将一些工作包装在一个对象中时,我们经常使用Operation
,它可以很好地将任务封装在自己的类中:
class SomeLongOperation: Operation
override func main()
// Runs a long loop and periodically checks `isCancelled`
while !isCancelled
Thread.sleep(forTimeInterval: 0.1)
print("tick")
并创建队列并将操作添加到该队列:
let queue = OperationQueue()
let operation = SomeLongOperation()
queue.addOperation(operation)
并取消操作:
operation.cancel()
或者
queue.cancelAllOperations()
底线,无论您使用Operation
(坦率地说,这是将某些任务包装在其自己的对象中的“首选”解决方案)还是使用DispatchWorkItem
自行滚动,想法都是一样的,即您不需要拥有自己的 state 属性来检测任务的取消。调度队列和操作队列都已经有了很好的机制来为你简化这个过程。
【讨论】:
【参考方案2】:我看到这个错误 (Weak properties are not thread safe when reading SR-192) 表明弱引用读取不是线程安全的,但它已被修复,这表明(在运行时没有任何错误),弱引用读取旨在是线程安全的.
也很有趣:Friday Q&A 2017-09-22: Swift 4 Weak References by Mike Ash
【讨论】:
以上是关于Swift - 检查弱变量是不是为 nil 或不是线程安全的?的主要内容,如果未能解决你的问题,请参考以下文章
Swift:尝试测试 ObservedObject 变量是不是为 nil 时的 EXC_BREAKPOINT
下划线符号是不是会忽略或检查 Swift 中 switch 语句中的无效性?