SwiftSafe 2.0.0

SwiftSafe 2.0.0

测试已测试
语言语言 SwiftSwift
许可证 MIT
发布上次发布2016年10月
SPM支持 SPM

Honza DvorskyDominik Hadl 维护。



SwiftSafe 2.0.0

  • Honza Dvorsky

SwiftSafe

线程同步变得容易。

为什么?

性能敏感的类需要内部状态同步,以确保外部访问器不会破坏内部不变量和引起竞态条件。直接使用 GCD (Grand Central Dispatch) 可能会使新手困惑,因为 API 并不一定反映使用它的实际原因。这就是为什么将 Swifty API 封装进其中可以给您的代码带来一点清晰的解释。下面是示例。

⌚️支持的并发模式

  • EREW - 独家读,独家写:最常用的同步方法,一次只能有一个线程读取或写入受保护的资源。一个很大的缺点是容易死锁。
  • CREW - 并发读,独家写:较少见,但在我看来更强大的方法,多个线程可以读取,但一次只能一个线程写入。读取和写入是自动独家执行的,即所有在写入之前排队等待读取的读取操作都将首先执行,然后执行单个写入操作,然后可以执行更多的读取操作(在写入之后排队的)。

📝要求

  • iOS 8.0+
  • Swift 3.0+

🎓用法

让我们假设您正在编写一个线程安全的 NSData 缓存。您希望它使用 CREW 访问以最大化性能。

class MyCache {
    private let storage: NSMutableDictionary = NSMutableDictionary()
    public func hit(key: String) -> NSData? {
        let found = self.storage[key]
        if let found = found {
            print("Hit for key \(key) -> \(found)")
        } else {
            print("Miss for key \(key)")
        }
        return found
    }
    public func update(key: String, value: NSData) {
        print("Updating \(key) -> \(value)")
        self.storage[key] = value
    }
}

这是第一个实现。它有效,但当您同时从多个线程调用它时,您将遇到不一致和竞态条件——意味着您将获得相同操作序列的不同结果。在更复杂的情况下,您甚至可能引起运行时崩溃。

修复它的方式明显是通过保护内部 storage(注意:NSDictionary 不是线程安全的)。同样,为了 Most 高效,您希望允许任何数量的线程从缓存中读取,但只允许一个线程更新它(并确保在此期间没有人正在读取它)。您可以使用 GCD 来实现这些保证,这正是 SwiftSafe 所做的。然而,此 API 带给桌面的是简单而明显的命名。

让我们看看我们如何在几行代码中将我们的缓存线程安全化。

import SwiftSafe

class MyCache {
    private let storage: NSMutableDictionary = NSMutableDictionary()
    private let safe: Safe = CREW()
    public func hit(key: String) -> NSData? {
        var found: NSData?
        safe.read {
            found = self.storage[key]
            if let found = found {
                print("Hit for key \(key) -> \(found)")
            } else {
                print("Miss for key \(key)")
            }
        }
        return found
    }
    public func update(key: String, value: NSData) {
        safe.write {
            print("Updating \(key) -> \(value)")
            self.storage[key] = value
        }
    }
}

这就完成了!只需导入库,创建一个遵循你想要实现的并发模式(在本例中是CREW)的 Safe 对象,并将对共享资源的访问封装在 readwrite 调用中。请注意,read 封闭调用总是 阻塞 调用线程,而 write 则不会。如果你有一个同时更新你的资源并从它读取的调用,请确保将该功能分成 写入读取 部分。这将使其推理和并行化变得更加容易。

👉总结

虽然对一些人来说可能看起来没有必要,但可理解和正确的方法的同步会为你省去几天调试和许多烦恼。 :)

💙行为准则

请注意,该项目以捐助者行为准则发布。通过参与此项目,你同意遵守其条款。

✌️许可证

MIT

👽作者

Honza Dvorsky - http://honzadvorsky.com@czechboy0