Cocoa和Objective-C 中加锁的方式有很多,但是在日常开发中最常用的应该是@synchronized,这个关键字可以用来修饰一个变量,并为其自动加上和解除互斥锁。这样,可以保证变量在作用范围内不会被其他线程改变
@synchronized(self) {
//给 self 加锁
}
虽然这个方法很简单好用,但是很不幸的是在Swift 中它已经不存在了
那么在swift 中想要用这样的方式加锁,改怎么办呢?
其实@synchronized 在幕后做的事情是调用了objc_sync 中的objc_sync_enter 和objc_sync_exit 方法,并且加入了一些异常判断。因此,在Swift 中,如果我们忽略掉那些异常的话,我们想要lock 一个变量的话,可以这样写:
public func synchronized<T>(_ lock: AnyObject, _ body: () throws -> T) rethrows -> T {
objc_sync_enter(lock)
defer { objc_sync_exit(lock) }
return try body()
}
调用的时候这样调用就可以了:
synchronized(self) {
//... 代码
}
给对象加锁
public class Synchronized<T> {
/// Private value. Use `public` `value` computed property (or `reader` and `writer` methods)
/// for safe, thread-safe access to this underlying value.
private var _value: T
/// Private reader-write synchronization queue
private var queue: DispatchQueue
/// Create `Synchronized` object
///
/// - Parameter value: The initial value to be synchronized.
/// queueName: The initial queueName
public init(_ value: T, queueName: String = "synchronized") {
_value = value
queue = DispatchQueue(label: Bundle.main.bundleIdentifier ?? "com.Synchronized" + "." + queueName, qos: .default, attributes: .concurrent)
}
/// A threadsafe variable to set and get the underlying object
public var value: T {
get { return queue.sync { _value } }
set { queue.async(flags: .barrier) { self._value = newValue } }
}
/// A "reader" method to allow thread-safe, read-only concurrent access to the underlying object.
///
/// - Warning: If the underlying object is a reference type, you are responsible for making sure you
/// do not mutating anything. If you stick with value types (`struct` or primitive types),
/// this will be enforced for you.
public func reader<U>(_ block: (T) throws -> U) rethrows -> U {
return try queue.sync { try block(_value) }
}
/// A "writer" method to allow thread-safe write with barrier to the underlying object
public func writer(_ block: @escaping (inout T) -> Void) {
queue.async(flags: .barrier) {
block(&self._value)
}
}
}
网友评论