Sobes.tech
Middle+

Qanday qilib race condition muammosini hal qilish mumkin?

sobes.tech AI

AIdan javob

Umumiy resurslarga kirishni sinxronlashtirish uchun iplar sinxronizasiyasidan foydalaning.

Asosiy yondashuvlar:

  • Mutexlar (Mutual Exclusion): Bir ip resursni ishlatayotganda, boshqa iplarning unga kirishini bloklaydi.
    • NSLock
    • os_unfair_lock
    • pthread_mutex_t
import Foundation

let lock = NSLock()
var sharedResource = 0

func modifyResource() {
    lock.lock() // Mutexni qo'lga kiritish
    // Tanqidiy bo'lim - xavfsiz kirish
    sharedResource += 1
    print("Resurs qiymati: \(sharedResource)")
    lock.unlock() // Mutexni bo'shatish
}

// Turli iplar bilan chaqirish misoli
// DispatchQueue.global().async { modifyResource() }
// DispatchQueue.global().async { modifyResource() }
  • Serial navbatlar: Vazifalarni ketma-ket bajaradi, faqat bitta kod bloki resursga kirish huquqiga ega bo'lishini kafolatlaydi.
    • DispatchQueue.main
    • DispatchQueue.global() .serial atributi bilan
import Foundation

let serialQueue = DispatchQueue(label: "com.example.serialQueue")
var sharedResource = 0

func modifyResourceAsync() {
    serialQueue.async {
        // Kod ketma-ket bajariladi
        sharedResource += 1
        print("Resurs qiymati: \(sharedResource)")
    }
}

// Turli iplar yoki navbatlar bilan chaqirish misoli
// modifyResourceAsync()
// modifyResourceAsync()
  • O'qiydigan-Yozuvchi blokirovkalar: Bir nechta iplar resursni o'qishi mumkin, lekin yozish faqat bitta ipga ruxsat etiladi.
    • DispatchQueue .barrier to'siqlari bilan
import Foundation

let concurrentQueue = DispatchQueue(label: "com.example.concurrentQueue", attributes: .concurrent)
var sharedResource = 0

func readResource() {
    concurrentQueue.async { // O'qish - bir vaqtning o'zida ko'p o'quvchilar
        print("Resursni o'qish: \(sharedResource)")
    }
}

func writeResource(newValue: Int) {
    concurrentQueue.sync(flags: .barrier) { // Yozish - faqat bitta yozuvchi va hech kim o'qimaydi/yazmaydi
        sharedResource = newValue
        print("Resursni yozish: \(sharedResource)")
    }
}

// Chaqirish misoli
// readResource()
// readResource()
// writeResource(newValue: 10)
// readResource()
  • Atomik operatsiyalar: Boshqa iplar tomonidan to'xtatilmasdan, to'liq bajariladigan operatsiyalar. Oddiy turlar uchun (hisoblagichlar, bayroqlar).
    • OSAtomicIncrement, OSAtomicDecrement (Eski, ammo konsept hozir ham amal qiladi)
    • <atomic> C++11 da
#include <atomic>
#include <iostream>

std::atomic<int> atomicCounter(0);

void incrementCounter() {
    atomicCounter++; // Atomik inkrement
    std::cout << "Hisoblagich: " << atomicCounter << std::endl;
}

// iOS kontekstida C++ misoli (Objective-C++ bilan foydalanish)
// Turli iplardan chaqirish
  • Qiymat turlari: Strukturalar yoki enumlarning nusxalarini uzatish, sinflarga nisbatan, ma'lumotlar o'rtasida raqobat shartlarini oldini olishga yordam berishi mumkin, agar ma'lumotlar to'g'ridan-to'g'ri o'zgartirilmaydigan tarzda iplar o'rtasida bo'lishmasa.

Usul tanlovi vazifa tabiatiga va talab qilingan parallelizm darajasiga bog'liq. iOSda ko'pchilik vazifalar uchun DispatchQueue (Serial va Concurrent, barierlar bilan) foydalanish qulayligi va Grand Central Dispatch (GCD) bilan integratsiya uchun afzalroq.