DispatchQueue: ano ito, pila ng GCD at mga batayan ng multi-threading

May-akda: IT Sectr Nai-publish: 2026-03-16 Oras ng pagbabasa: 8 min

Ang DispatchQueue ay isang pangunahing pila ng framework na Grand Central Dispatch (GCD) para sa pamamahala ng mga asynchronous na gawain sa iOS at macOS. Ayon sa Apple Developer Documentation, 2026, ang DispatchQueue ay nag-aabstrak ng pamamahala ng thread mula sa developer sa pamamagitan ng serial at concurrent na mga pila. Awtomatikong namamahagi ang GCD ng mga gawain sa system thread pool, inaalis ang manu-manong paglikha at pagwasak ng mga thread.

Mga pangunahing punto

  • DispatchQueue — pangunahing abstraksyon ng GCD para sa asynchronous na pagpapatupad ng code sa iOS
  • Serial na pila nagsasagawa ng mga gawain nang mahigpit na sunud-sunod, inaalis ang kondisyon ng karera
  • Concurrent na pila nagpapatakbo ng maraming gawain nang magkatulad sa pamamagitan ng system thread pool
  • QoS nagtatakda ng priyoridad ng gawain — mula userInteractive hanggang background
  • DispatchQueue.main — ang tanging pila para sa pag-update ng UIKit sa pangunahing thread

Ano ang DispatchQueue at Grand Central Dispatch

DispatchQueue ay isang bagay ng framework na Grand Central Dispatch (GCD) na namamahala sa pagpapatupad ng mga gawain sa system o custom na mga pila ng thread. Ang Grand Central Dispatch ay isang mababang antas na aklatan ng Apple, magagamit mula noong iOS 4 at macOS 10.6, na ganap na nag-aabstrak ng pamamahala ng thread mula sa developer. Gumagamit ang GCD ng thread pool ng operating system at awtomatikong nag-scale ng bilang ng mga thread sa ilalim ng load ng device.

Hindi kailangan ng developer na manu-manong lumikha at magwasak ng mga thread — GCD ang pumapalit sa gawaing ito, na nagbibigay ng simpleng API sa pamamagitan ng DispatchQueue. Ang gawain sa anyo ng closure ay ipinapadala sa pila sa pamamagitan ng mga pamamaraang sync o async. Sa unang kaso, ang tumatawag na thread ay naba-block hanggang sa makumpleto ang gawain, sa pangalawa — agad na nagpapatuloy sa pagpapatupad.

Ayon sa Apple (2026), ang GCD ay gumagamit ng system thread pool na umaangkop sa bilang ng mga core at kasalukuyang load ng processor. Ang concurrent na pila ay hindi lumilikha ng bagong thread para sa bawat gawain — muling ginagamit ng GCD ang mga thread mula sa pool, na nagpapaliit ng overhead sa paglikha ng thread.

Arkitektura ng GCD

Ang Grand Central Dispatch ay binubuo ng tatlong pangunahing bahagi: ang pila (DispatchQueue), ang grupo (DispatchGroup), at ang semaphore (DispatchSemaphore). Ang pila ay ang pangunahing elemento na tumatanggap ng mga gawain sa anyo ng mga bloke ng code. Pinag-synchronize ng DispatchGroup ang pagpapatupad ng maraming gawain, at nililimitahan ng DispatchSemaphore ang access sa isang shared resource sa isang tiyak na bilang ng mga thread.

Ang bawat pila ng GCD ay nauugnay sa isang partikular na klase ng QoS (Quality of Service) na nagpapaalam sa system tungkol sa kahalagahan ng gawain. Ginagamit ng system ang QoS para sa pamamahagi ng oras ng processor sa pagitan ng mga pila, na nagbibigay ng priyoridad sa mas kritikal na mga gawain — halimbawa, pag-update ng UI o pagproseso ng mga pagpindot ng user.

Serial at Concurrent na mga pila: paghahambing

Serial na pila ay nagsasagawa ng mga gawain nang mahigpit na sunud-sunod, isa-isa. Kung tatlong gawain ang ilalagay sa serial na pila, ang pangalawa ay magsisimula lamang pagkatapos ng ganap na pagkumpleto ng una. Ginagamit ang serial na mga pila para sa pag-synchronize ng access sa mga shared resource — halimbawa, sa isang array na binabago mula sa maraming bahagi ng code.

Concurrent na pila ay nagpapatakbo ng maraming gawain nang sabay-sabay, ipinamamahagi ang mga ito sa mga available na thread mula sa system pool. Ang mga gawain sa concurrent na pila ay nagsisimula sa pagkakasunud-sunod ng pagdating (FIFO), ngunit nagtatapos sa arbitraryong pagkakasunud-sunod kung magkaiba ang oras ng pagpapatupad. Concurrent na pila ay hindi ginagarantiyahan ang pagkakasunud-sunod ng pagkumpleto — tanging ang pagkakasunud-sunod ng pagsisimula.

ParameterSerial na pilaConcurrent na pila
Pagkakasunud-sunod ng pagpapatupadMahigpit na sunud-sunodMagkatulad
Bilang ng mga threadIsaMarami mula sa pool ng GCD
PaggamitProteksyon ng shared resourceMalayang pag-compute
Main queueOo (pangunahing thread)Hindi
Panganib ng deadlockMataas sa sync sa parehong pilaMababa

Kailan pumili ng serial na pila

Ang serial na pila ay mainam para sa mga gawain na nagbabago ng shared state — pagsulat sa file, pag-update ng modelo ng data, o pagtatrabaho sa Core Data. Ang paggamit ng serial na pila ay ginagarantiyang ang dalawang bahagi ng code ay hindi sabay na magbabago ng parehong data, inaalis ang kondisyon ng karera nang walang karagdagang pagla-lock.

Kailan pumili ng concurrent na pila

Concurrent na pila ay angkop para sa mga gawaing hindi nakadepende sa isa't isa: pag-load ng maraming larawan, parallel na network request, o batch processing ng data. Awtomatikong nagpapasya ang GCD kung gaano karaming gawain ang sabay na patakbuhin, batay sa bilang ng mga core ng processor at kasalukuyang load ng system.

Quality of Service: mga priyoridad ng pagpapatupad ng gawain

QoS (Quality of Service) — mekanismo ng GCD na nagpapaalam sa operating system tungkol sa kahalagahan at pagka-apura ng gawain. Ginagamit ng system ang QoS para sa pag-iskedyul ng mga thread: ang mga gawain na may mas mataas na QoS ay nakakakuha ng mas maraming oras ng processor at mas maagang nasisimulan. Ang halaga ng QoS ay ipinapadala kapag lumilikha ng pila o nagpapadala ng partikular na gawain.

Sa GCD, limang klase ng QoS ang available. .userInteractive — pinakamataas na priyoridad para sa mga gawaing nauugnay sa UI. .userInitiated — para sa mga gawaing pinasimulan ng user. .utility — para sa mga gawain sa background na may pagpapakita ng progreso. .background — para sa mga gawaing hindi nakikita ng user. .default — antas sa pagitan ng userInitiated at utility, ginagamit bilang default.

Ayon sa Apple (2026), ang maling pagpili ng QoS ay isa sa mga karaniwang sanhi ng mga problema sa performance. Ang pagpapatakbo ng background download na may QoS .userInteractive ay kumukuha ng mga mapagkukunan mula sa UI, na nagdudulot ng micro-lag sa mga animation. Inirerekomenda na piliin ang pinakamababang QoS na nagbibigay pa rin ng katanggap-tanggap na oras ng pagpapatupad.

Halimbawa ng paggamit ng QoS

Kapag nag-load ng larawan para sa agarang pagpapakita, gamitin ang .userInitiated — inaasahan ng user ang resulta. Para sa preloading ng susunod na screen, sapat na ang .utility. Ang background synchronization sa server ay isinasagawa gamit ang .background, na pinapaliit ang epekto sa mga aktibong gawain.

DispatchGroup at semaphores: pag-synchronize ng gawain

DispatchGroup ay nagbibigay-daan sa pagsubaybay sa pagkumpleto ng isang grupo ng mga gawain. Kapag ang lahat ng gawain sa grupo ay natapos, tinatawag ng GCD ang notify handler sa tinukoy na pila. Ito ay lalong kapaki-pakinabang kapag naglo-load ng maraming independiyenteng mapagkukunan — data ng profile, listahan ng kaibigan, at mga setting — kapag ang interface ay kailangang i-update lamang pagkatapos matanggap ang lahat ng data.

Sinusuportahan ng DispatchGroup ang synchronous na tawag na wait() na nagba-block sa kasalukuyang thread hanggang sa makumpleto ang lahat ng gawain. Ito ay maginhawa kapag ang code ay hindi maaaring magpatuloy nang wala ang mga resulta ng grupo. Ang asynchronous na variant — notify() — ay tumatawag sa closure sa tinukoy na pila pagkatapos ng pagkumpleto ng lahat ng gawain, nang hindi nagba-block sa tumatawag na thread.

DispatchSemaphore para sa paglilimita ng paralelismo

DispatchSemaphore ay kumokontrol sa access sa isang resource, na nililimitahan ang bilang ng sabay-sabay na pag-access. Ang semaphore na may paunang halaga na 3 ay nagpapahintulot sa pagpapatakbo ng hindi hihigit sa tatlong parallel na gawain. Kapag tinawag ang wait(), bumababa ang counter, kapag signal() — tumataas. Kung ang counter ay zero, ang thread ay naba-block hanggang sa mapalaya ang resource.

Mga halimbawa ng code gamit ang DispatchQueue sa Swift

Tingnan natin ang tatlong praktikal na halimbawa ng paggamit ng DispatchQueue sa Swift. Ang una ay nagpapakita ng pangunahing async na tawag na may pagbabalik sa pangunahing thread, ang pangalawa — pag-synchronize sa pamamagitan ng serial na pila, ang pangatlo — DispatchGroup para sa parallel na mga request.

Pangunahing async na tawag na may pagbabalik sa main

DispatchQueue.main ay ang serial na pila ng pangunahing thread, na eksklusibong inilaan para sa mga operasyon ng UI. Palaging gamitin ito para sa pag-update ng interface pagkatapos makumpleto ang background work.

swift
let queue = DispatchQueue.global(qos: .userInitiated)
queue.async {
    let data = self.fetchData()
    DispatchQueue.main.async {
        self.updateUI(with: data)
    }
}

Serial na pila para sa proteksyon ng shared resource

Ang paglikha ng iyong sariling serial na pila na may natatanging identifier ay nag-synchronize ng access sa isang mutable array. Lahat ng read at write operation ay dumadaan sa isang pila, inaalis ang kondisyon ng karera.

swift
let serialQueue = DispatchQueue(label: "com.app.items")
var items: [Int] = []

serialQueue.async {
    items.append(1)
}
serialQueue.async {
    let last = items.last
    DispatchQueue.main.async {
        print("Last item: \(last)")
    }
}

DispatchGroup para sa parallel na mga request

DispatchGroup ay nagpapahintulot sa pagpapatakbo ng maraming gawain sa isang concurrent na pila at pagtanggap ng abiso kapag lahat ay natapos na. Ito ay kapaki-pakinabang kapag naglo-load ng data para sa screen ng profile.

swift
let group = DispatchGroup()
let worker = DispatchQueue.global()

worker.async(group: group) { self.loadProfile() }
worker.async(group: group) { self.loadFriends() }
worker.async(group: group) { self.loadSettings() }

group.notify(queue: DispatchQueue.main) {
    self.showCompleteUI()
}

Mga karaniwang pagkakamali sa pagtatrabaho sa DispatchQueue

Deadlock sa sync na tawag sa isang serial na pila — ang pinakakaraniwang pagkakamali. Kung ang isang gawain sa isang serial na pila ay tumawag ng queue.sync sa parehong pila, ang thread ay permanente naba-block. Ang pila ay naghihintay ng pagkumpleto ng kasalukuyang gawain, at ang gawain ay naghihintay ng pagkumpleto ng sync na tawag — isang klasikong mutual deadlock.

Pag-update ng UI mula sa background thread

Lahat ng operasyon sa UIKit ay dapat isagawa sa pangunahing thread. Nakikita ng Xcode ang mga pagkakamaling ito sa Debug mode sa pamamagitan ng Main Thread Checker. Sa Release build, humahantong ang mga ito sa hindi mahuhulaan na pag-uugali: hindi tumatakbo ang mga animation, hindi naa-update ang UI, posible ang mga crash.

Labis na paglikha ng custom na mga pila

Ang paglikha ng daan-daang custom na pila sa halip na global na mga pila ay isang anti-pattern. Bawat pila ay kumokonsumo ng mga system resources. Para sa karamihan ng mga gawain, sapat na ang global na concurrent na mga pila na may iba't ibang QoS at isa-dalawang serial na pila para sa pag-synchronize ng shared data.

Pagbalewala ng autoreleasepool sa mga loop

Kapag nagsasagawa ng resource-intensive cyclic na mga gawain sa isang background na pila nang walang autoreleasepool, ang memorya ay lumalaki hanggang sa matapos ang buong loop. Ang ARC ay naglalabas ng mga object lamang kapag lumalabas sa autorelease pool. Balutin ang mga iteration ng loop sa autoreleasepool { } para sa napapanahong pagpapalaya ng memorya.

Mga madalas itanong

Ano ang pagkakaiba ng DispatchQueue at OperationQueue?

OperationQueue ay binuo sa ibabaw ng GCD, ngunit nagbibigay ng mas mataas na antas ng API na may mga dependency ng operasyon, KVO, at suporta sa pagkansela. Ang DispatchQueue ay isang mababang antas na pila para sa simpleng async na mga gawain nang walang pamamahala ng dependency.

Maaari bang puwersahang ihinto ang isang gawain sa DispatchQueue?

Hindi sinusuportahan ng GCD ang paghinto ng isang tumatakbong gawain. Ang pamamaraang suspend() ay nagpa-pause lamang ng mga bagong gawain, ang kasalukuyang gawain ay tumatakbo hanggang sa matapos. Para sa pagkansela, kailangan ang manu-manong pagsusuri ng flag sa loob ng code ng gawain.

Aling QoS ang dapat piliin para sa network request?

Para sa pangunahing request na may agarang pagpapakita ng resulta — .userInitiated. Para sa preloading ng data — .utility. Para sa background synchronization — .background.

Ilang thread ang ginagamit ng concurrent na pila?

Hindi itinatakda ng GCD ang bilang ng mga thread. Ang thread pool ay dynamic na nag-scale sa ilalim ng load, isinasaalang-alang ang mga core ng processor, kasalukuyang load, at QoS ng bawat gawain. Ang maximum na bilang ay nililimitahan ng system.

Bakit ang DispatchQueue.main ay sapilitan para sa UIKit?

Ang UIKit ay hindi thread-safe — lahat ng mga klase nito ay dapat tawagin lamang mula sa pangunahing thread. Ang paglabag ay nagdudulot ng hindi mahuhulaan na pag-uugali, mga na-miss na update, at mga crash sa produksyon.

Buod

  • DispatchQueue — pangunahing kasangkapan ng Grand Central Dispatch para sa asynchronous na mga gawain sa iOS at macOS
  • Serial na pila nagsasagawa ng mga gawain nang sunud-sunod, inaalis ang kondisyon ng karera nang walang pagla-lock
  • Concurrent na pila nagpapatakbo ng mga gawain nang magkatulad sa pamamagitan ng system thread pool
  • QoS tumutukoy sa priyoridad ng gawain — mula userInteractive hanggang background
  • DispatchGroup nag-synchronize ng maraming parallel na gawain na may notify sa pangunahing thread
  • Deadlock sa sync sa isang abalang serial na pila — kritikal na pagkakamali na nangangailangan ng pansin
  • Main thread ay sapilitan para sa UIKit — i-update ang interface lamang sa pamamagitan ng DispatchQueue.main

Gagawa kami ng mobile application na turnkey

Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.

Pag-usapan ang proyekto

Basahin din