Sobes.tech
Middle+

Yarış şərti (race condition) problemini necə həll etmək olar?

sobes.tech Süni İntellekt

AI-dan cavab

Ümumi resurslara giriş üçün axınların sinxronizasiyasından istifadə etmək.

Əsas yanaşmalar:

  • Mutexlər (Müəyyənləşdiricilər): Bir axın resursu istifadə etdikdə, digər axınların ona girişini bloklayır.
    • NSLock
    • os_unfair_lock
    • pthread_mutex_t
import Foundation

let lock = NSLock()
var sharedResource = 0

func modifyResource() {
    lock.lock() // Müəyyənləşdiricini ələ keçirmək
    // Kritikal bölmə - sharedResource-ə təhlükəsiz giriş
    sharedResource += 1
    print("Resurs dəyəri: \(sharedResource)")
    lock.unlock() // Müəyyənləşdiricini azad etmək
}

// Fərqli axınlardan çağırış nümunəsi
// DispatchQueue.global().async { modifyResource() }
// DispatchQueue.global().async { modifyResource() }
  • Serial Queue-lar (Serial növbələr): Tapşırıqları bir-bir yerinə yetirir, eyni zamanda yalnız bir blok kod resursa giriş edə bilər.
    • DispatchQueue.main
    • DispatchQueue.global().serial atributu ilə
import Foundation

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

func modifyResourceAsync() {
    serialQueue.async {
        // Kod ardıcıllıqla icra olunur
        sharedResource += 1
        print("Resurs dəyəri: \(sharedResource)")
    }
}

// Fərqli axınlar/növbələrdən çağırış nümunəsi
// modifyResourceAsync()
// modifyResourceAsync()
  • Oxucu-Yazıcı Lock-ləri (Reader-Writer Locks): Bir çox axın resuru oxuya bilər, amma yalnız bir axın yaza bilər.
    • DispatchQueue.barrier ilə yazma və oxuma üçün sinxron və asinxron giriş.
import Foundation

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

func readResource() {
    concurrentQueue.async { // Oxuma - çox oxucu eyni zamanda
        print("Resursu oxuyur: \(sharedResource)")
    }
}

func writeResource(newValue: Int) {
    concurrentQueue.sync(flags: .barrier) { // Yazma - yalnız bir yazar və heç kim oxumur/yazmır
        sharedResource = newValue
        print("Resursu yazır: \(sharedResource)")
    }
}

// Çağırış nümunələri
// readResource()
// readResource()
// writeResource(newValue: 10)
// readResource()
  • Atomik Əməliyyatlar (Atomic Operations): Bir axın tərəfindən tam və kəsilmədən yerinə yetirilən əməliyyatlar. Sadə tipli məlumatlar üçün istifadə olunur (sayğaclar, bayraqlar).
    • OSAtomicIncrement, OSAtomicDecrement (Köhnə olsa da, konsept aktualdır)
    • C++11 <atomic>
#include <atomic>
#include <iostream>

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

void incrementCounter() {
    atomicCounter++; // Atomik artım
    std::cout << "Sayğac: " << atomicCounter << std::endl;
}

// iOS kontekstində C++ nümunəsi (Objective-C++ ilə istifadə)
// Fərqli axınlardan çağırmaq
  • Dəyər Növləri (Value Types): Strukturların və ya enumerasiyaların nüsxələrini ötürmək, məlumatların yarışmasını qarşısını almağa kömək edə bilər, əgər məlumatlar birbaşa paylaşılmırsa və dəyişdirilməzdirsə.

Yöntəmin seçimi vəzifənin xüsusiyyətlərinə və tələb olunan paralellik səviyyəsinə bağlıdır. iOS-də əksər hallarda DispatchQueue (Serial və Concurrent, barierlərlə) istifadə etmək daha asandır və Grand Central Dispatch (GCD) ilə inteqrasiya olunur.