在多个线程中使用空引用实例的安全性

问题描述

背景

我有一个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")
    }
}

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...