并发和锁定 Swift

Concurrency and lock in Swift

前提

我们都知道宇宙中有好数字坏数字

我有以下同步函数

func isGood(number:Int) -> Bool {
    // synchronous connection
    // ...
    // returns a Bool
}

当然我没有在这里提供秘密实现,但你应该知道它执行 同步 互联网连接并且它 return

问题

现在,给定从 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
        }
    }
}

问题

  1. 如何保证同步访问Swift中lineAlineB之间的代码块?
  2. 最后,一旦我得到结果,是否可以杀死仍在处理的并发闭包?

提前致谢。

建立在巨人的肩膀上!

  1. 我会用 https://github.com/ReactiveCocoa/ReactiveCocoa/blob/v3.0-RC.1/ReactiveCocoa/Swift/Atomic.swift 来激励自己,并使用他们的 lock/unlock 机制。
  2. 据我所知,没有办法 'kill' 闭包——这听起来可能是使用提供取消机制的 NSOperation 数组的情况(尽管它应该请注意,实际上由您在 NSOperation 中的适当位置检查 isCancelled 标志,以便您可以停止它正在做的任何工作。
  1. serial queue 可用于同步对特定资源的访问。
  2. 我不确定。如果有办法 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
        }
    }
}