Middle+
რა არის iOS-ის ყველაზე ნათელი deadlock-ის მაგალითი, რომელსაც შეგიძლიათ მოყვანა?
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колдонулганда, фондук агым аяктоо үчүн, негизги агым блокту аткарганга чейин күтүшү керек. Эгер негизги агым блоктолгон болсо (мисалы, фондук агымдагы операциянын аяктоосун күтүп жатса, ал өз кезегинде негизги агымды күтүп жатса же жөн эле иштөөдө болсо), цикл түзүлүп, deadlock пайда болот.
Туура чечим:
UI жаңыртууну асинхрондук түрдө негизги агымга жөнөтүү:
// Туура чечим: UI жаңыртууну асинхрондук түрдө негизги агымда жүргүзүү
DispatchQueue.global().async {
// Ар кандай фондук ишти аткарып жатабыз...
print("Фондук иш жүрүп жатат")
// UI жаңыртууну асинхрондук түрдө жөнөтөбүз
DispatchQueue.main.async {
print("UI жаңыртууда")
// someLabel.text = "Фондук иштен жаңыртылды" // UI жаңыртуунун туура жери
}
print("Фондук иш аяктады")
}
Бул жерде, фондук агым блокту негизги агымга жөнөтүүдө блоктолбойт, бул фондук жана негизги агымдар өз алдынча иштей алат дегенди билдирет жана deadlock алдын алат.