首页 > 解决方案 > iOS Swift5 将使用带锁的 NSMutableDictionary 而不是 var [:] 确保线程安全?

问题描述

我正在调试一个我在项目中继承的 swift 类。曾尝试使用带有信号量的 swift 字典创建线程安全字典。代码在多线程环境中失败 - swift 字典被视为结构并在突变时复制,无论信号量如何。

我试图理解:用核心基础 NSMutableDictionary(带有信号量)替换基于 swift 结构的字典会确保代码的线程安全吗?

我看到了 Objective-C 的这个答案,但我的问题是关于修改 swift 代码。

public class ThreadSafeDictionary<KeyType: Hashable, ValueType> {

    private var dictionary: [KeyType: ValueType] = [:]
    //change to:
    private let dictionary = NSMutableDictionary() //will this make the mutating code thread safe?

    public func add(key: KeyType, value: ValueType) {
    // semaphore wait
    // set value in dictionary
    // semaphore signal
    }
}

或者 - 有没有办法使用像mutatinginout这样的 swift 关键字来确保信号量会阻止多个线程每个都使用 swift 字典的副本?

更新:更高级别的代码中有一个错误,创建了 2 个独立的 ThreadSafeDictionary 实例。修复该问题解决了并发问题。

标签: iosthread-safetynsmutabledictionaryswift5

解决方案


如果您将 Swift 目录(例如 struct)包装到 Swift 类(引用类型)中,您将不知何故失去 struct 的写时复制机制(这确实是为了防止多线程问题)。因此,如果将内部directory成员从 Swift 类型更改为 Foundation 的NSMutableDirectory. 此外,mutating或者inout不暗示任何线程安全。

为了使ThreadSafeDictionary线程安全,您需要包装内部目录的所有访问方法,如您在func add...()函数中所描述的。除了使用信号量,您还可以将 GCD 与您自己的串行队列一起使用。


推荐阅读