← Назад к вопросам
Что такое многопоточность (multithreading)?
1.3 Junior🔥 121 комментариев
#Многопоточность и асинхронность
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Chto takoe Mnogopotochnost' - Multithreading
Mnogopotochnost' (Multithreading) - eto vozmozhnost' vypolnjat' neskolko zadach odnovremenno v ramkakh odnogo processa. Na monoyadernykh CPU - time-sharing, na mnogoyadernykh - istinnyj parallel'izm. Eto fundamental'nyj koncept dlja reaktivnyh, nedolauchih iOS prilozhenyj.
Osnovna ideja
Bez mnogopotochnosti:
Task1 -> Task2 -> Task3
S mnogopotochnost'yu:
Thread1: Task1 ---> Task3
Thread2: Task2 ----->
Main Thread - UI potok
Glavnyj potok vypolnjaet VSEY UI updatey. Esli ego zablokirovat' - UI zamerznet:
overrride func viewDidLoad() {
let data = try? Data(contentsOf: url)
imageView.image = UIImage(data: data)
}
Eto blokiruet main thread, UI zavisivaet. Nuzhen backgroundovyj potok:
overrride func viewDidLoad() {
DispatchQueue.global().async {
let data = try? Data(contentsOf: url)
DispatchQueue.main.async {
self.imageView.image = UIImage(data: data)
}
}
}
Dispatch Queues (GCD)
Apple rekomenduet ispol'zovat' GCD vmesto prjamyh Thread:
DispatchQueue.main.async {
self.label.text = "Updated"
}
DispatchQueue.global().async {
let result = doExpensiveWork()
DispatchQueue.main.async {
self.updateUI(with: result)
}
}
let customQueue = DispatchQueue(label: "com.myapp.processing")
customQueue.async {
processData()
}
Quality of Service (QoS) - prioritety
DispatchQueue.global(qos: .userInteractive).async {
// UI animacii, 0.1ms otvet
}
DispatchQueue.global(qos: .userInitiated).async {
// Search, filter, 1ms otvet
}
DispatchQueue.global(qos: .utility).async {
// Download, import, 100ms
}
DispatchQueue.global(qos: .background).async {
// Maintenance, 1sec
}
Race Conditions - opasnost'
Mnogo potkov pristupajut k odnim dannym:
var counter = 0
// DANGEROUS - data race
for i in 0..<1000 {
DispatchQueue.global().async {
counter += 1
}
}
// SAFE - serial queue
let serialQueue = DispatchQueue(label: "counter")
for i in 0..<1000 {
serialQueue.async {
counter += 1
}
}
Serial vs Concurrent Queues
Serial - po ocheredi:
let queue = DispatchQueue(label: "serial")
queue.async { print("1") }
queue.async { print("2") }
queue.async { print("3") }
// Output: 1 2 3
Concurrent - parallel'no:
let queue = DispatchQueue(label: "concurrent", attributes: .concurrent)
queue.async { print("A") }
queue.async { print("B") }
queue.async { print("C") }
// Output: A B C (v lyubom porjadke)
Synchronization Primitives
Semaphore:
let semaphore = DispatchSemaphore(value: 2)
for i in 0..<5 {
DispatchQueue.global().async {
semaphore.wait()
print("Processing")
sleep(1)
semaphore.signal()
}
}
Lock:
let lock = NSLock()
lock.lock()
data.append(42)
lock.unlock()
Async/Await - modern podkhod
async {
let data = await fetchData()
updateUI(with: data)
}
func fetchData() async -> Data {
return try? await URLSession.shared.data(from: url).0
}
Prakticheskij primer
func downloadImages(urls: [URL]) {
let queue = DispatchQueue(label: "downloads", attributes: .concurrent)
let semaphore = DispatchSemaphore(value: 3)
for url in urls {
queue.async {
semaphore.wait()
let image = downloadImage(from: url)
DispatchQueue.main.async {
self.updateUI(with: image)
}
semaphore.signal()
}
}
}
Opasnosti
- Deadlock - dva potoka zhdut drug druga
- Race conditions - nedeterminirovannoe sostojanie
- Memory leaks - silnye ssylki v closures
- UI blokirovka - ne na main thread
Rekomendacii
- Ispol'zuй async/await vmesto GCD
- Main thread dlja UI tolko
- Concurrent queue dlja parallel'noj raboty
- Serial queue dlja ekskluzivnogo dostupa
- Izbeгaj deep nesting
Mnogopotochnost' - kljuch k bystromu i reaktivnomu iOS prilozhenju.