Grand Central Dispatch - атомная собственность и состояние гонки - PullRequest
0 голосов
/ 02 марта 2019

Я пытаюсь углубить параллельное программирование с помощью swift, в частности, GCD.Я слежу за этим .И когда я думаю, что понимаю, есть некоторые моменты, которые заставляют меня полностью передумать.Скажите мне, в чем я не прав, если я ошибаюсь.

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

Поэтому я скопировал видеокод, добавив только инициализатор, и создал условия для выполнения условия гонки.

Оставляя код, как описано в видео, возникает состояние гонки !!результат: свойство InternalSate не является атомарным, как я.

Вместо того, чтобы выполнять второй тест и перемещать внутреннюю очередь из методов get и set в метод changeState, все работает как надо.

Фактически, это, казалось бы, лучший способ действовать: workingQueue создает поток для каждой итерации в цикле for и делает это асинхронно, каждый поток выполняет код changeState ().Если два потока создаются за короткое время, второй может выполнить строку let temp = состояние до того, как первый выполнит состояние записи = temp + 1. По сути, критический сеанс находится в changeState (), а не в пределах get и set.

Я что-то пропустил?Я был не прав с рассуждениями?Под кодом, который я использовал.

class MyObject {
private var internalState: Int
private let internalQueue: DispatchQueue

init() {
    internalState = 0;
    internalQueue = DispatchQueue(label: "com.myQueue")
}

var state: Int {
    get {
        return internalQueue.sync { internalState } // COMMENT THIS FOR SECOND PART
//            print("GET from thread \(Thread.current) get: \(internalState)") // UNCOMMENT THIS FOR SECOND PART
//            return internalState // UNCOMMENT THIS FOR SECOND PART

    }
    set (newState) {
        internalQueue.sync { internalState = newState } // COMMENT THIS FOR SECOND PART
//            internalState = newState  // UNCOMMENT THIS FOR SECOND PART
//            print("SET from thread \(Thread.current) write: \(newState)")  // UNCOMMENT THIS FOR SECOND PART
    }
}

func changeState(){
    let temp = state // COMMENT THIS FOR SECOND PART
    state = temp + 1 // COMMENT THIS FOR SECOND PART

//        internalQueue.sync {  // UNCOMMENT THIS FOR SECOND PART
//            let temp = state  // UNCOMMENT THIS FOR SECOND PART
//            state = temp + 1  // UNCOMMENT THIS FOR SECOND PART
//        }// UNCOMMENT THIS FOR SECOND PART
}

}

let workingQueue = DispatchQueue.global()
let myGroup = DispatchGroup()
myGroup.notify(queue: DispatchQueue.global()){
print("END ...")
}

let myObject = MyObject()

for _ in 0...9 {
    workingQueue.async {
        myObject.changeState()
    }
}

sleep(4)

myObject.state
...