Middle+
iOS-те ең жарқын дедлок мысалы ретінде не келтіруге болады?
sobes.tech AI
AI-дан жауап
iOS-та дедлоктың ең жарқын мысалы фондық ағыннан UI-ды жаңартуға тырысқанда арнайы механизмдерді қолданбайтын кезде пайда болады.
// Бұл код дедлок немесе қате шақыруға әкелуі мүмкін (iOS нұсқасына және контекстке байланысты)
// негізгі ағыннан шақырылмай тұрғанда
DispatchQueue.global().async {
// Кейбір фондық жұмыс...
print("Фондық жұмыс орындалуда")
// Фондық ағыннан тікелей UI-ды жаңартуға тырысу
// Бұл UIKit-тің қауіпсіз емес екендігін көрсетеді
DispatchQueue.main.syncが必要です!
// Бұл мәселені көрсету үшін қосылған - нақты кодта мұндай жасауға болмайды!
DispatchQueue.main.sync {
// Негізгі ағындағы белгішені жаңарту
// Бірақ біз бұрын синхронды түрде негізгі ағынды күтудеміз, ол бұғатталған
// біздің өзіміздің синхронды жіберу блогымызбен
print("UI-ды жаңартуға тырысу")
// someLabel.text = "Фоннан жаңартылды" // Мәселені тудыратын жолдың мысалы
}
print("Фондық жұмыс аяқталды")
}
Түсіндірме:
UIKit (iOS-та қолданушы интерфейсін құру үшін қолданылатын framework) қауіпсіз емес. Барлық UI операциялары тек негізгі ағында орындалуы керек (main thread).
Жоғарыда көрсетілген мысалда, егер DispatchQueue.main.sync { ... } блогын фондық ағыннан шақырсақ, онда:
- Фондық ағын бұғатталады және негізгі ағынның оған жіберілген код блогын орындауын күтеді.
- Негізгі ағын сол уақытта бос болуы мүмкін немесе, бұл сценарийде ықтимал, өзі бір операцияның аяқталуын күтуде, ол фондық ағыннан басталуы керек еді (бірақ нақты мысалда бұл жоқ, фондық ағыннан негізгі ағынға синхронды жіберу мәселе туғызады).
syncжағдайында, фондық ағын өз жұмысын аяқтай алмайды, себебі негізгі ағын жіберілген блогты орындап жатқанда, ол бұғатталған болуы мүмкін (мысалы, фондық ағыннан операцияны күтуде және ол да негізгі ағынды күтуде), нәтижесінде циклдік күтім пайда болады, яғни дедлок.
Дұрыс шешім:
UI-ды жаңарту үшін асинхронды түрде негізгі ағынға жіберу керек.
// Дұрыс шешім: UI-ды асинхронды түрде негізгі ағында жаңарту
DispatchQueue.global().async {
// Кейбір фондық жұмыс...
print("Фондық жұмыс орындалуда")
// UI-ды асинхронды түрде негізгі ағынға жіберу
DispatchQueue.main.async {
print("UI-ды негізгі ағында жаңарту")
// someLabel.text = "Фоннан жаңартылды" // UI-ды жаңарту үшін дұрыс орын
}
print("Фондық жұмыс аяқталды")
}
Бұл жерде фондық ағын блокты негізгі ағынға жіберген кезде бұғатталмайды, бұл фондық тапсырма мен негізгі ағынның тәуелсіз жұмыс істеуін қамтамасыз етеді, осылайша дедлоктан сақтайды.