use*_*195 3 multithreading swift
在一个可能有多个线程运行的应用程序中,并且不确定是否可以在多线程环境下访问这些方法但是为了安全,我已经做了一个测试类来演示一个情况.
一种方法has被编程为线程安全(如果做得对,也请评论)但其余的不是.
在这样的情况下,那里只有一个内部一行代码remove和add,是有必要使他们线程安全的,或者它会是夸张.
import Foundation
class Some {}
class Test {
var dict = [String: Some]()
func has(key: String) -> Bool {
var has = false
dispatch_sync(dispatch_queue_create("has", nil), { [unowned self] in
has = self.dict[key] != nil
})
return has
}
func remove(key: String) -> Some {
var ob = dict[key]
dict[key] = nil
return ob
}
func add(key: String, ob: Some) {
dict[key] = ob
}
}
Run Code Online (Sandbox Code Playgroud)
评论后编辑
class Some {}
class Test {
var dict = [String: Some]()
private let queue: dispatch_queue_t = dispatch_queue_create("has", DISPATCH_QUEUE_CONCURRENT)
func has(key: String) -> Bool {
var has = false
dispatch_sync(queue) {
has = self.dict[key] != nil
}
return has
}
func remove(key: String) -> Some? { //returns
var removed: Some?
dispatch_barrier_sync(queue) {
removed = self.dict.removeValueForKey(key)
}
return removed
}
func add(key: String, ob: Some) { //not async
dispatch_barrier_sync(queue) {
self.dict[key] = ob
}
}
}
Run Code Online (Sandbox Code Playgroud)
检查密钥是否存在的方式不正确.您每次都在创建一个新队列,这意味着操作不会同步进行.
我这样做的方式是这样的:
class Some {}
class Test {
var dict = [String: Some]()
private let queue: dispatch_queue_t = dispatch_queue_create("has", DISPATCH_QUEUE_CONCURRENT)
func has(key: String) -> Bool {
var has = false
dispatch_sync(queue) { [weak self] in
guard let strongSelf = self else { return }
has = strongSelf.dict[key] != nil
}
return has
}
func remove(key: String) {
dispatch_barrier_async(queue) { [weak self] in
guard let strongSelf = self else { return }
strongSelf.dict[key] = nil
}
}
func add(key: String, ob: Some) {
dispatch_barrier_async(queue) { [weak self] in
guard let strongSelf = self else { return }
strongSelf.dict[key] = ob
}
}
}
Run Code Online (Sandbox Code Playgroud)
首先,我创建了一个串行队列,它将用于访问字典作为对象的属性,而不是每次都创建一个新的.该队列是私有的,因为它仅在内部使用.
当我想从类中获取一个值时,我只是同步地向队列调度一个块,并在返回之前等待块完成,无论队列是否存在.由于这不会改变字典,因此在并发队列上运行此类多个块是安全的.
当我想在字典中添加或删除值时,我将块添加到队列中,但是有一个屏障.这样做的是它在队列运行时停止队列中的所有其他块.完成后,所有其他块可以同时运行.我正在使用异步调度,因为我不需要等待返回值.
想象一下,您有多个线程试图查看键值是否存在或添加或删除值.如果你有很多读取,那么它们会同时发生,但是当其中一个块运行会改变字典时,所有其他块都会等到这个改变完成后再开始运行.
通过这种方式,您可以获得在获取值时并发运行的速度和便利性,以及在字典变异时阻塞的线程安全性.
编辑添加
selfweak在块中标记为不会创建引用循环.正如@MartinR在评论中提到的那样; 当块仍然在队列中时,对象可能被释放,如果发生这种情况,那么self是未定义的,并且您可能会在尝试访问字典时遇到运行时错误,因为它也可能被解除分配.
通过将self块内的声明设置为弱,如果对象存在,则self不会为nil,并且可以有条件地将strongSelf其解包到哪些点中self并且还创建强引用,以便self在块中的指令为止时不会释放.执行.当这些说明完成后,strongSelf将超出范围并释放对自我的强烈参考.
这有时被称为"强自我,弱自我舞蹈".
再次编辑:Swift 3版本
class Some {}
class Test {
var dict = [String: Some]()
private let queue = DispatchQueue(label: "has", qos: .default, attributes: .concurrent)
func has(key: String) -> Bool {
var has = false
queue.sync { [weak self] in
guard let strongSelf = self else { return }
has = strongSelf.dict[key] != nil
}
return has
}
func remove(key: String) {
queue.async(flags: .barrier) { [weak self] in
guard let strongSelf = self else { return }
strongSelf.dict[key] = nil
}
}
func add(key: String, ob: Some) {
queue.async(flags: .barrier) { [weak self] in
guard let strongSelf = self else { return }
strongSelf.dict[key] = ob
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1541 次 |
| 最近记录: |