Состояние гонки с использованием GCD в Swift - PullRequest
0 голосов
/ 04 июня 2018

Я пытаюсь смоделировать состояние гонки, позволяя нескольким потокам читать и записывать общее состояние.Но как-то в итоге результат верный.Ниже приведен код, который я использую для имитации поведения.

import Foundation
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true

let queue = DispatchQueue(label: "my-queue", qos: .userInitiated, attributes: [.concurrent, .initiallyInactive])
var val = 0
let group = DispatchGroup()
group.enter()
queue.async {
    for _ in 0..<100 {
        val += 1
    }
    group.leave()
}

group.enter()
queue.async {
    for _ in 0..<100 {
        val += 1
    }
    group.leave()
}

queue.activate()

group.notify(queue: DispatchQueue.main) {
    print("Done incrementing final value is \(val)")
}

Вывод: Завершено с увеличением конечного значения 200

Вопрос в том, каким будет конечный вывод 200, когда несколько потоков читают и записывают одно значение?

1 Ответ

0 голосов
/ 04 июня 2018

Этого не может быть на детской площадке.Попробуйте запустить его в реальном приложении.

Единственный способ, которым два потока могут мешать друг другу, - это если один поток читает значение val между временем, в течение которого другой поток читает значение и увеличивает его.Вам, скорее всего, просто повезло, так как время между чтением val и записью его с увеличенным значением действительно крошечно.Разделите чтение и запись и введите задержку (с usleep), и вы увидите условие гонки:

let queue = DispatchQueue(label: "my-queue", qos: .userInitiated, attributes: [.concurrent, .initiallyInactive])
var val = 0
let group = DispatchGroup()
group.enter()
queue.async {
    for _ in 0..<100 {
        let value = val
        usleep(10_000)
        val = value + 1
        print("val = \(val)")
    }
    group.leave()
}

group.enter()
queue.async {
    for _ in 0..<100 {
        let value = val
        usleep(9_000)
        val = value + 1
        print("val = \(val)")
    }

    group.leave()
}

queue.activate()
...