Sobes.tech
Middle+

Yarış durumu (race condition) sorununu nasıl çözersiniz?

sobes.tech yapay zeka

AI'dan gelen yanıt

Paylaşılan kaynaklara erişmek için iş parçacığı senkronizasyonu kullanın.

Ana yaklaşımlar:

  • Mutexler (Karşılıklı dışlama): Bir iş parçacığı kullanırken diğerlerinin erişimini engeller.
    • NSLock
    • os_unfair_lock
    • pthread_mutex_t
import Foundation

let lock = NSLock()
var sharedResource = 0

func modifyResource() {
    lock.lock() // Mutex'i al
    // Kritik bölüm - sharedResource'a güvenli erişim
    sharedResource += 1
    print("Kaynak değeri: \(sharedResource)")
    lock.unlock() // Mutex'i serbest bırak
}

// Farklı iş parçacıklarından çağrı örneği
// DispatchQueue.global().async { modifyResource() }
// DispatchQueue.global().async { modifyResource() }
  • Seri Kuyruklar: Görevleri sırayla yürütür, aynı anda yalnızca bir kod bloğunun kaynağa erişimini sağlar.
    • DispatchQueue.main
    • DispatchQueue.global() .serial özniteliği ile
import Foundation

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

func modifyResourceAsync() {
    serialQueue.async {
        // Kod bu kuyrukta sıralı olarak çalışır
        sharedResource += 1
        print("Kaynak değeri: \(sharedResource)")
    }
}

// Farklı iş parçacıkları/kuyruklar ile çağrı örneği
// modifyResourceAsync()
// modifyResourceAsync()
  • Okuyucu-Yazıcı Kilitleri: Birden çok iş parçacığının aynı anda okuyabilmesine izin verir, ancak yalnızca birinin yazmasına.
    • DispatchQueue .barrier bariyerleri ile
import Foundation

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

func readResource() {
    concurrentQueue.async { // Okuma - çok sayıda okuyucu aynı anda
        print("Kaydı okuma: \(sharedResource)")
    }
}

func writeResource(newValue: Int) {
    concurrentQueue.sync(flags: .barrier) { // Yazma - tek yazar ve kimse okumaz/yazmaz
        sharedResource = newValue
        print("Kayda yazma: \(sharedResource)")
    }
}

// Çağrı örneği
// readResource()
// readResource()
// writeResource(newValue: 10)
// readResource()
  • Atomik İşlemler: Diğer iş parçacıklarının kesintiye uğramadan tam olarak gerçekleştirilmesini garanti eden işlemler. Basit veri tipleri (sayıcılar, bayraklar) için kullanılır.
    • OSAtomicIncrement, OSAtomicDecrement (Eski, ancak kavram geçerliliğini koruyor)
    • <atomic> C++11'de
#include <atomic>
#include <iostream>

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

void incrementCounter() {
    atomicCounter++; // Atomik artış
    std::cout << "Sayaç: " << atomicCounter << std::endl;
}

// iOS bağlamında C++ örneği (Objective-C++ ile kullanım)
// Farklı iş parçacıklarından çağır
  • Değer Tipleri: Yapıların/enumların kopyalarını geçirmek, referanslar yerine, veriler doğrudan paylaşılmadığında yarış koşullarını önlemeye yardımcı olabilir.

İşlev seçimi, görevin doğasına ve gereken paralellik seviyesine bağlıdır. iOS'ta çoğu görev için DispatchQueue (Seri ve Bariyerli Paralel) kullanımı, kullanım kolaylığı ve Grand Central Dispatch (GCD) ile entegrasyonu nedeniyle tercih edilir.