Search code examples
swiftswift-concurrency

Tasks always seem to run in order in Swift code


This code always seems to work like magic. Without any locking, the output is 1,2.

class Counter {
    var count = 0
    func increment() -> Int {
        count += 1
        return count
    }
}

class ViewController: UIViewController {
    
    var tasks = [Task<Void, Never>]()

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let counter = Counter()
        
        tasks += [
            Task.detached {
                print(counter.increment())
            }
        ]

        tasks += [
            Task.detached {
                print(counter.increment())
            }
        ]
    }
}

This code is from https://www.andyibanez.com/posts/understanding-actors-in-the-new-concurrency-model-in-swift/

I'm expecting it to work inconsistently. I've tried switching it to not use detached tasks, but still it always returns 1,2. What is going on?


Solution

  • First, on Simulator, this only uses a single thread (*), so you won't see it get out of order with this code. On device, it uses multiple threads, but you probably won't see it out of order very often for just 2 tasks. If you re-write this with 100 tasks and run on device, it's very easy to show what you're looking for.

        for _ in 1...100 {
            tasks += [
                Task.detached {
                    print(counter.increment())
                }
            ]
        }
    
    1
    5
    7
    8
    9
    10
    11
    ...
    

    (*) I've been told by folks I trust that Simulator uses 2 threads, at least now (I haven't run tests to check). This still causes the same symptom, since one is dedicated to main.