iOS - NSCache 如何确保线程安全

pin*_*shw 4 multithreading thread-safety ios nscache

我想实现一个线程安全的MutableDataContainer. 当然,我可以简单的加一个锁来进行读写操作,但是在我的项目中,我需要经常读取数据,所以我不想使用这种方式。

有谁知道NSCache是如何实施的?

drk*_*itz 5

我不完全确定 NSCache 专门使用的锁定机制,但我建议特别是在 Apple 平台的现代开发中的 5 种解决方案之一,这可能是实现 NSCache 的方式之一。可能有 5 种以上,此列表并不详尽。我只是不包括更多,因为在我看来,我不相信 Apple 会使用此处未包括的方法。

以下所有方法都有效,但我将努力不让自己听起来对哪种方法更好(我们将看到结果如何)发表意见,因为这不是您的问题的真正含义。此外,关于这个主题有很多我不想煽风点火的意见。我将要讨论的是,基于这些方法和我对 Apple 的看法,就我认为 NSCache 的实现方式提供我的看法。

  1. pthread 库的 pthread RW 锁。这是专为同步而设计的,并且具有锁可以提供的性能,而简单的互斥锁(RW 锁实际使用的是什么)所不能提供的性能。对于读取,您使用 获得锁pthread_rwlock_rdlock,而对于写入,您使用 获得锁pthread_rwlock_wrlock。在下面,这本质上是一个递归锁,并且在写入之前不应该实际阻止读取。这优化了更常见的读取路径,并安全地考虑了不太常见的写入路径。对于更不常见的读/写操作,您必须基本上将其提升为写入。使用 pthread 锁(或互斥锁)时,您可以根据自己的代码逻辑和内部明确定义的条件来优化您的锁,尽管我不会在这里讨论。

  2. GCD 库的串行队列 - 使用串行队列时,可disaptch_sync用于读取和dispatch_async写入。这与优化公共路径的 pthread RW 锁不同,因为读取和写入都是串行的。尽管它确实依赖 GCD 来优化读取及其底层队列优化(例如 GCD 确定何时适当地阻塞dispatch_sync调用)。对于更不常见的读/写操作,您只需将其视为读取并使用dispatch_sync. 这也是,因为这种方法与之前的方法有一个重要区别,即虽然读取应该是快速的并且通过 GCD 进行优化,但它们仍然是串行的,在技术上仍然相互阻塞。

  3. GCD 库的并发队列 - 在使用并发队列时,您可以dispatch_sync用于读取和dispatch_barrier_async写入。对于读/写的特殊情况,dispatch_barrier_sync几乎是专门为此目的而制作的。在这个世界上,读取永远不会相互阻塞,并且在遇到屏障之前根本不会阻塞,屏障是为写和读/写保留的。这种方法还依赖于 GCD 来优化读取,但是通过使用并发队列,您将选择退出串行读取。因此,基本上由您来控制必须串行的事物,并在这些操作需要时使用屏障。

  4. Foundation 框架NSLock- 这是Foundation 框架的经典构造。尽管它的原始实现可能有所不同,但最近我查看了它的内部构造,在我测试过的所有情况下,它本质上是一个围绕相应 pthread 实现的 Objective-C 包装器。

  5. Objective-C's @synchronized()- 这是一个内置的 Objective-C 函数/关键字,提供锁定和异常处理。它的底层本质上是一个带有异常处理程序的 NSLock。使用它时,它用于读取和写入。在内部,它们被同等对待,因此没有针对另一个进行优化。您的锁与您传递给@synchronized(obj)函数的对象相关联。因此,本质上,您正在锁定对该对象的访问,而不管它在相应的“@synchronized() {}”块中如何使用或改变。

每种方法都有更多的细节和注意事项,但如果我是一个赌徒(我不是),并且基于我将在此之后进行的一些事情,我会说 Apple 正在使用方法 #3 来处理 NSCache .

原因 1:Apple 关注性能,尤其是 Foundation。自 GCD 成立以来,他们就对其进行了大量投资,并将继续对其进行投资。创建 GCD 的大部分原因是基于在不牺牲性能的情况下尽可能多地删除样板。我想说的是,Apple 可能正在对他们在 Foundation 内部的一些地方提出的建议进行狗食,而 NSCache 可能就是其中之一。

原因2:有点“原因1继续”,最近有更多的证据表明苹果在GCD上的投资和在.js上的投资不足@synchonized(),这在Swift中可以看到。GCD 是 Swift 中首选的同步方法。

  • 看起来 NSCache 的 Swift 实现使用了旧的普通 NSLock:https://github.com/apple/swift-corelibs-foundation/blob/master/Foundation/NSCache.swift (2认同)