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.
NSLockos_unfair_lockpthread_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.mainDispatchQueue.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.barrierbariyerleri 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.