Middle+
Ի՞նչ է ամենաուշագրավ օրինակն of deadlock in iOS, որը կարող եք բերել։
sobes.tech AI
Պատասխան AI-ից
Իմաստուն օրինակ է iOS-ում deadlock-ի, երբ փորձում ենք UI-ն թաքնված հոսքից թարմացնել հատուկ մեխանիզմների օգտագործումից բացի:
// Այս կոդը կհանգեցնի deadlock կամ կոտրվելու (կախված iOS-ի տարբերակից և կոնտեքստից)
// երբ կանչվում է գլխավոր հոսքից դուրս
DispatchQueue.global().async {
// Կատարում ենք որոշ ֆոնային աշխատանք...
print("Ֆոնային աշխատանքը կատարվում է")
// Փորձում ենք ուղղակիորեն թարմացնել UI-ն ֆոնային հոսքից
// Դա կհանգեցնի արտահայտության կամ deadlock-ի, քանի որ UIKit-ը չի ապահովում հոսքային անվտանգություն
DispatchQueue.main.syncが必要です!
// Սա ավելացվել է խնդրի ցուցադրման համար - իրական կոդում այդպես անել չի կարելի!
DispatchQueue.main.sync {
// Փորձում ենք թարմացնել նշանը գլխավոր հոսքում
// Բայց քանի որ մենք արդեն սինխրոն սպասում ենք գլխավոր հոսքին, որը բլոկավորված է
// մեր սեփական սինխրոն ուղարկման բլոկով, առաջանում է deadlock:
print("Փորձում ենք թարմացնել UI-ն")
// someLabel.text = "Թարմացվել է ֆոնից" // Օրինակ տող, որը կարող է խնդիր առաջացնել
}
print("Ֆոնային աշխատանքը ավարտվեց")
}
Նկարագրություն:
UIKit (ֆրեյմվորկ՝ օգտագործողի ինտերֆեյսի կառուցման համար iOS-ում) չի ապահովում հոսքային անվտանգություն: Բոլոր 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-ը։