Sobes.tech
Middle

Ի՞նչ է մրցավազքի պայմանը (race condition):

sobes.tech AI

Պատասխան AI-ից

Ռիսկային վիճակը առաջանում է, երբ երկու կամ ավելի թելեր կամ գործընթացներ միաժամանակ դիմում են ընդհանուր ռեսուրսի (օրինակ, փոփոխական, ֆայլ, տվյալների բազա) և գործողության արդյունքը կախված է նրանից, թե ինչ կարգով են դրանք կատարում իրենց գործողությունները: Դրա պատճառով տվյալների մուտքի և փոփոխության անորոշ կարգի պատճառով արդյունքը կարող է լինել սխալ կամ անսպասելի:

Օրինակ iOS-ում: Ենթադրենք, ունենք հաշվիչ count, որի վրա միաժամանակ դիմում են երկու թելեր՝ ավելացման համար:

var count = 0

func incrementCount() {
    // Թել 1-ը կարդում է count = 5
    // Թել 2-ը կարդում է count = 5
    let currentCount = count
    // Թել 1-ը հաշվարկում է newCount = 6
    // Թել 2-ը հաշվարկում է newCount = 6
    let newCount = currentCount + 1
    // Թել 1-ը գրում է count = 6
    // Թել 2-ը գրում է count = 6 (գրառում է Թել 1-ի արդյունքը)
    count = newCount
}

// Եթե երկու թելերը միաժամանակ կանչեն incrementCount(),
// սպասվող արդյունքը կլինի count = 2,
// բայց ռիսկային վիճակի պատճառով count կարող է լինել 1:

Ռիսկային վիճակների կանխարգելման համար կիրառվում են սինխրոնիզացիայի մեխանիզմներ՝

  • Lock/Mutex: Բլոկավորում է ռեսուրսի հասանելիությունը, մինչ այն օգտագործում է թելը:
    import Foundation
    
    let lock = NSLock()
    var count = 0
    
    func incrementCount() {
        lock.lock() // Բլոկի գրավում
        let currentCount = count
        let newCount = currentCount + 1
        count = newCount
        lock.unlock() // Բլոկի ազատում
    }
    
  • Հոսքեր (Queues): Օգտագործում է հերթական GCD հոսքեր՝
    import Foundation
    
    let serialQueue = DispatchQueue(label: "com.myapp.counterQueue")
    var count = 0
    
    func incrementCount() {
        serialQueue.async {
            let currentCount = count
            let newCount = currentCount + 1
            count = newCount
        }
    }
    
  • Ատոմային օպերացիաներ: Անվտանգ գործողություններ պրոցեսորի հրահանգների մակարդակով: Swift-ում կարելի է օգտագործել OSAtomic... (հնացած) կամ Atomic``@_implementationOnly import Atomics-ից (փորձարարական), կամ այլ մոտեցումներ՝ բլոկավորումների կամ հերթերի հիման վրա:

Սինխրոնիզացիայի մեթոդի ընտրությունը կախված է կոնկրետ սցենարից և կատարողականի պահանջներից:

Հիմնական է հասկանալ, որ սինխրոնիզացիան կարող է ավելացնել բեռը և հնարավոր է հանգեցնի միմյանց փակման (deadlock), եթե սխալ իրականացվի։