如何解决在多个线程中使用空引用实例的安全性
背景
我有一个Data
类,它存储多个输入参数和一个输出值。
只要输入参数之一发生突变,就会重新计算输出值。
该计算耗时很短,因此它是异步执行的。
如果在重新计算过程中输入参数之一发生更改,则当前计算被取消,并开始新的计算。
取消逻辑是通过计算操作和键(参考实例)(Data.key
)的序列化队列来实现的。每次将新的重新计算添加到队列时,Data.key
都会设置为新的参考实例。由于队列的原因,一次只能进行一次重新计算。任何执行中的重新计算都会通过同时保留对启动时使用它创建的密钥和当前存在的密钥的引用来不断检查它是否是最近启动的计算。如果它们不同,则自开始以来已进行了新的重新计算,然后将终止。
这将触发队列中的下一次重新计算开始,重复该过程。
我的问题的依据
Data.key
的重新分配是在主线程上完成的。
当前计算不断检查其密钥是否与当前密钥相同。这意味着另一个线程正在不断访问Data.key
。
问题
让Data.key
易于同时读取/写入容易吗?
是否甚至可以同时读取和写入属性?
解决方法
问:
对我来说,让Data.key易于同时读取/写入是否安全?
A:
不
问:
甚至有可能同时读取和写入属性?
A:
是的,为Data.Key创建一个单独的队列,您只能通过该队列访问它。只要此队列中限制了任何操作(获取/设置),就可以在线程安全的情况下从任何地方读取或写入。
,
是的Data.Key易于同时读取/写入。
这是我从主线程写入密钥并从MySerialQueue读取密钥的示例。
如果运行该代码,有时会崩溃。
崩溃的发生是由于指针的取消指向主队列写入期间释放的内存所致。
Xcode具有称为ThreadSanitizer的功能,它将有助于捕获此类问题。
Discussion About Race condition
func experiment() {
var key = MyClass()
var key2 = MyClass()
class MyClass {}
func writer() {
for _ in 0..<1000000 {
key = MyClass()
}
}
func reader() {
for _ in 0..<1000000 {
if key === key2 {}
}
}
DispatchQueue.init(label: "MySerialQueue").async {
print("reader begin")
reader()
print("reader end")
}
DispatchQueue.main.async {
print("writer begin")
writer()
print("writer end")
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。