并发和锁定 Swift
Concurrency and lock in Swift
前提
我们都知道宇宙中有好数字和坏数字。
我有以下同步函数
func isGood(number:Int) -> Bool {
// synchronous connection
// ...
// returns a Bool
}
当然我没有在这里提供秘密实现,但你应该知道它执行 同步 互联网连接并且它 return
true
:如果作为参数接收的 Int
是 "good number"
false
:否则
问题
现在,给定从 0 到 99 的 100 个整数,我想知道其中是否至少有 51 个是好数字。
同步方法
我可以写这样的东西。
func majorityIsGood() -> Bool {
var count = 0
for i in 0...99 {
if isGood(i) {
count++
if count > 50 {
return true
}
}
}
return false
}
但是对 isGood
执行 100 次(在最坏的情况下)同步调用将需要太多时间。我需要尽快得到答案。
异步方法
我更喜欢这样的东西
func majorityIsGood(completion:(good:Bool) -> ()) {
var goodNums = 0
var badNums = 0
var resultFound = false
for i in 0...99 {
dispatch_async(DISPATCH_QUEUE_CONCURRENT) {
let isGood = isGood(i)
// lineA
// begin lock on (resultFound)
if !resultFound {
if isGood {
goodNums++
} else {
badNums++
}
if goodNums > 50 || badNums >= 50 {
resultFound = true
completion(good: goodNums > 50)
}
}
// end lock on (resultFound)
// lineB
}
}
}
问题
- 如何保证同步访问Swift中
lineA
和lineB
之间的代码块?
- 最后,一旦我得到结果,是否可以杀死仍在处理的并发闭包?
提前致谢。
建立在巨人的肩膀上!
- 我会用 https://github.com/ReactiveCocoa/ReactiveCocoa/blob/v3.0-RC.1/ReactiveCocoa/Swift/Atomic.swift 来激励自己,并使用他们的
lock
/unlock
机制。
- 据我所知,没有办法 'kill' 闭包——这听起来可能是使用提供取消机制的
NSOperation
数组的情况(尽管它应该请注意,实际上由您在 NSOperation
中的适当位置检查 isCancelled
标志,以便您可以停止它正在做的任何工作。
serial queue
可用于同步对特定资源的访问。
- 我不确定。如果有办法 kill 正在分派的并发操作。但是,如果您只是想 停止 它们。查看
NSOperation
取消。
这是代码
func majorityIsGood( completion: ((good:Bool) -> Void) ) {
var goodNums = 0
var badNums = 0
var resultFound = false
let serialQueue = dispatch_queue_create("com.unique.myQueue", DISPATCH_QUEUE_SERIAL)
for i in 0...99 {
dispatch_async(DISPATCH_QUEUE_CONCURRENT) {
let _isGood = isGood(i)
// lineA
dispatch_async(serialQueue){
if !resultFound {
if _isGood {
goodNums++
} else {
badNums++
}
if goodNums > 50 || badNums >= 50 {
resultFound = true
completion(good: goodNums > 50)
}
}
}
// lineB
}
}
}
前提
我们都知道宇宙中有好数字和坏数字。
我有以下同步函数
func isGood(number:Int) -> Bool {
// synchronous connection
// ...
// returns a Bool
}
当然我没有在这里提供秘密实现,但你应该知道它执行 同步 互联网连接并且它 return
true
:如果作为参数接收的Int
是 "good number"false
:否则
问题
现在,给定从 0 到 99 的 100 个整数,我想知道其中是否至少有 51 个是好数字。
同步方法
我可以写这样的东西。
func majorityIsGood() -> Bool {
var count = 0
for i in 0...99 {
if isGood(i) {
count++
if count > 50 {
return true
}
}
}
return false
}
但是对 isGood
执行 100 次(在最坏的情况下)同步调用将需要太多时间。我需要尽快得到答案。
异步方法
我更喜欢这样的东西
func majorityIsGood(completion:(good:Bool) -> ()) {
var goodNums = 0
var badNums = 0
var resultFound = false
for i in 0...99 {
dispatch_async(DISPATCH_QUEUE_CONCURRENT) {
let isGood = isGood(i)
// lineA
// begin lock on (resultFound)
if !resultFound {
if isGood {
goodNums++
} else {
badNums++
}
if goodNums > 50 || badNums >= 50 {
resultFound = true
completion(good: goodNums > 50)
}
}
// end lock on (resultFound)
// lineB
}
}
}
问题
- 如何保证同步访问Swift中
lineA
和lineB
之间的代码块? - 最后,一旦我得到结果,是否可以杀死仍在处理的并发闭包?
提前致谢。
建立在巨人的肩膀上!
- 我会用 https://github.com/ReactiveCocoa/ReactiveCocoa/blob/v3.0-RC.1/ReactiveCocoa/Swift/Atomic.swift 来激励自己,并使用他们的
lock
/unlock
机制。 - 据我所知,没有办法 'kill' 闭包——这听起来可能是使用提供取消机制的
NSOperation
数组的情况(尽管它应该请注意,实际上由您在NSOperation
中的适当位置检查isCancelled
标志,以便您可以停止它正在做的任何工作。
serial queue
可用于同步对特定资源的访问。- 我不确定。如果有办法 kill 正在分派的并发操作。但是,如果您只是想 停止 它们。查看
NSOperation
取消。
这是代码
func majorityIsGood( completion: ((good:Bool) -> Void) ) {
var goodNums = 0
var badNums = 0
var resultFound = false
let serialQueue = dispatch_queue_create("com.unique.myQueue", DISPATCH_QUEUE_SERIAL)
for i in 0...99 {
dispatch_async(DISPATCH_QUEUE_CONCURRENT) {
let _isGood = isGood(i)
// lineA
dispatch_async(serialQueue){
if !resultFound {
if _isGood {
goodNums++
} else {
badNums++
}
if goodNums > 50 || badNums >= 50 {
resultFound = true
completion(good: goodNums > 50)
}
}
}
// lineB
}
}
}