我已经搜索了Swift的书籍,但找不到@synchronized的Swift版本。我如何做互斥在Swift?
当前回答
您可以创建propertyWrapper synchronized
这里是NSLock下罩的例子。你可以使用任何你想要的同步GCD, posix_locks等
@propertyWrapper public struct Synchronised<T> {
private let lock = NSLock()
private var _wrappedValue: T
public var wrappedValue: T {
get {
lock.lock()
defer {
lock.unlock()
}
return _wrappedValue
}
set {
lock.lock()
defer {
lock.unlock()
}
_wrappedValue = newValue
}
}
public init(wrappedValue: T) {
self._wrappedValue = wrappedValue
}
}
@Synchronised var example: String = "testing"
基于@drewster的答案
其他回答
使用Bryan McLemore的答案,我扩展了它,以支持使用Swift 2.0延迟能力扔进安全庄园的对象。
func synchronized( lock:AnyObject, block:() throws -> Void ) rethrows
{
objc_sync_enter(lock)
defer {
objc_sync_exit(lock)
}
try block()
}
我喜欢并使用了这里的许多答案,所以我会选择最适合你的。也就是说,当我需要objective-c的@synchronized时,我更喜欢使用swift 2中引入的defer语句。
{
objc_sync_enter(lock)
defer { objc_sync_exit(lock) }
//
// code of critical section goes here
//
} // <-- lock released when this block is exited
这个方法的好处是,你的临界区可以以任何想要的方式退出包含块(例如,return, break, continue, throw),并且“不管程序控制如何转移,defer语句中的语句都将被执行”。1
为什么要让锁变得困难和麻烦呢? 使用分派障碍。
调度障碍在并发队列中创建同步点。 当它正在运行时,队列上的其他块都不允许运行,即使它是并发的并且其他内核可用。 如果这听起来像一个排他(写)锁,它是。 无障碍块可以被认为是共享(读)锁。 只要所有对资源的访问都是通过队列执行的,barrier就能提供非常廉价的同步。
Dispatch_barrier_async是更好的方法,同时不会阻塞当前线程。
dispatch_barrier_async (accessQueue, { 字典对象。ID = object })
细节
Xcode 8.3.1, Swift 3.1
Task
从不同的线程读写值(异步)。
Code
class AsyncObject<T>:CustomStringConvertible {
private var _value: T
public private(set) var dispatchQueueName: String
let dispatchQueue: DispatchQueue
init (value: T, dispatchQueueName: String) {
_value = value
self.dispatchQueueName = dispatchQueueName
dispatchQueue = DispatchQueue(label: dispatchQueueName)
}
func setValue(with closure: @escaping (_ currentValue: T)->(T) ) {
dispatchQueue.sync { [weak self] in
if let _self = self {
_self._value = closure(_self._value)
}
}
}
func getValue(with closure: @escaping (_ currentValue: T)->() ) {
dispatchQueue.sync { [weak self] in
if let _self = self {
closure(_self._value)
}
}
}
var value: T {
get {
return dispatchQueue.sync { _value }
}
set (newValue) {
dispatchQueue.sync { _value = newValue }
}
}
var description: String {
return "\(_value)"
}
}
使用
print("Single read/write action")
// Use it when when you need to make single action
let obj = AsyncObject<Int>(value: 0, dispatchQueueName: "Dispatch0")
obj.value = 100
let x = obj.value
print(x)
print("Write action in block")
// Use it when when you need to make many action
obj.setValue{ (current) -> (Int) in
let newValue = current*2
print("previous: \(current), new: \(newValue)")
return newValue
}
完整的样品
扩展DispatchGroup
extension DispatchGroup {
class func loop(repeatNumber: Int, action: @escaping (_ index: Int)->(), completion: @escaping ()->()) {
let group = DispatchGroup()
for index in 0...repeatNumber {
group.enter()
DispatchQueue.global(qos: .utility).async {
action(index)
group.leave()
}
}
group.notify(queue: DispatchQueue.global(qos: .userInitiated)) {
completion()
}
}
}
类ViewController
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//sample1()
sample2()
}
func sample1() {
print("=================================================\nsample with variable")
let obj = AsyncObject<Int>(value: 0, dispatchQueueName: "Dispatch1")
DispatchGroup.loop(repeatNumber: 5, action: { index in
obj.value = index
}) {
print("\(obj.value)")
}
}
func sample2() {
print("\n=================================================\nsample with array")
let arr = AsyncObject<[Int]>(value: [], dispatchQueueName: "Dispatch2")
DispatchGroup.loop(repeatNumber: 15, action: { index in
arr.setValue{ (current) -> ([Int]) in
var array = current
array.append(index*index)
print("index: \(index), value \(array[array.count-1])")
return array
}
}) {
print("\(arr.value)")
}
}
}
推荐文章
- 在Swift中转换字符串为日期
- 点击按钮时如何打开手机设置?
- 在Swift中使用自定义消息抛出错误/异常的最简单方法?
- 编译器错误:带有Objective-C选择器的方法与前面带有相同Objective-C选择器的声明冲突
- 如何在Swift中获得唯一的设备ID ?
- 如何在Swift中获得枚举值的名称?
- 互斥实例/教程?
- 如何调用手势点击在UIView编程在迅速
- 什么是Swift相当于respondsToSelector?
- dyld:库未加载:@rpath/libswift_stdlib_core.dylib
- 我如何隐藏在一个Swift iOS应用程序的状态栏?
- 以编程方式更改导航标题
- 我如何得到一个plist作为一个字典在Swift?
- 如何在Swift中删除视图的所有子视图?
- 属性getter和setter