简体   繁体   English

Swift中的并发和锁定

[英]Concurrency and lock in Swift

Premise 前提

We all know there are good numbers and bad numbers in the universe. 我们都知道宇宙中有很多数字坏数字

I have the following synchronous function 我有以下同步功能

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

Of course I am not providing the secret implementation here, but you should know that it performs a synchronous internet connection and it does return 当然,我不是在这里提供秘密实现,但你应该知道它执行同步互联网连接并确实返回

  • true : if the Int received as param is a "good number" true :如果作为参数收到的Int是一个“好数字”
  • false : otherwise false :否则

The problem 问题

Now, given the 100 integers from 0 to 99, I want to know if at least 51 of them are good numbers. 现在,假设从0到99的100个整数,我想知道它们中至少有51个是好数字。

The synchronous approach 同步方法

I could write something like this. 我可以写这样的东西。

func majorityIsGood() -> Bool {
    var count = 0
    for i in 0...99 {
        if isGood(i) {
            count++
            if count > 50 {
                return true
            }
        }
    }
    return false
}

But performing 100 (in the worst case scenario) synchronous call to isGood will require too much time. 但是执行100(在最坏的情况下)同步调用isGood将需要太多时间。 I need the answer as fast as possible. 我需要尽快得到答案。

The asynchronous approach 异步方法

I would prefer something like this 我更喜欢这样的东西

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
        }
    }
}

Questions 问题

  1. How can I guarantee a synchronous access to the block of code between lineA and lineB in Swift? 如何保证同步访问Swift中lineAlineB之间的代码块?
  2. And finally, once I get the result, is it possible to kill the concurrent closures that are still being processed? 最后,一旦我得到结果,是否有可能杀死仍在处理的并发闭包?

Thank you in advance. 先感谢您。

  1. serial queue can be used to synchronize access to a specific resource. serial queue可用于同步对特定资源的访问。
  2. I'm not sure. 我不确定。 If there is a way to kill the concurrent operation that being dispatched. 如果有办法杀死正在调度的并发操作。 However, if you just want to stop them. 但是,如果你只是想阻止它们。 take a look at NSOperation cancellation. 看看NSOperation取消。

Here's the code 这是代码

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
        }
    }
}

Build on the shoulders of giants! 建立在巨人的肩膀上!

  1. I would inspire myself with https://github.com/ReactiveCocoa/ReactiveCocoa/blob/v3.0-RC.1/ReactiveCocoa/Swift/Atomic.swift and use their lock / unlock mechanism. 我会用https://github.com/ReactiveCocoa/ReactiveCocoa/blob/v3.0-RC.1/ReactiveCocoa/Swift/Atomic.swift激发自己,并使用他们的lock / unlock机制。
  2. As far as I know there is no way to 'kill' closures — that sounds like it could be a case for using an array of NSOperation s which provide a cancellation mechanism (although it should be noted that it is actually up to you to check the isCancelled flag at appropriate points in your NSOperation so that you can stop whatever work it is doing. 据我所知,没有办法“杀死”闭包 - 这听起来像是使用NSOperation数组提供取消机制的情况(尽管应该注意到它实际上取决于你检查在你的NSOperation中的适当点处的isCancelled标志,这样你就可以停止正在做的任何工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM