U ovom članku ćemo istražiti probleme koje želi riješiti, objasniti kako radi pod kapom, usporediti novi model s prethodnim i detaljnije pogledati model Actor.U narednim dijelovima, takođe ćemo razdvojiti izvršitelje, rasporednike, strukturiranu konkurenciju, različite vrste izvršitelja, implementirati vlastiti izvršitelj i još mnogo toga. Swift Pregled konkurencije: Problemi i rešenja Pisanje koda koji istovremeno pokreće zadatke može poboljšati performanse i odgovornost, ali često uvodi složenost i suptilne greške kao što su uvjeti utrke, zamke i problemi sa bezbednošću. Swift Concurrency, uveden u Swift 6, ima za cilj da pojednostavi istovremeno programiranje pružanjem jasnog, sigurnog i efikasnog modela za rukovanje asinkronim zadatcima. 💡Ako koristite Swift 5.x i planirate da migrirate na Swift 6, možete omogućiti Swift Concurrency provjere u postavkama projekta. To vam omogućuje da postepeno usvojite novi concurrency model dok održavate kompatibilnost sa postojećim kodom. Omogućavanje ovih provjera pomaže da se ranije uhvate potencijalni problemi s concurrentom, čineći prijelaz glatkim i sigurnijim. Kako ažurirate bazu kodova, možete početi integrisati async/await sintaksu i druge funkcije Swift Concurrency postepeno bez potpunog prepisivanja. 💡Ako koristite Swift 5.x i planirate da migrirate na Swift 6, možete omogućiti Swift Concurrency provjere u postavkama projekta. To vam omogućuje da postepeno usvojite novi model konkurencije dok održavate kompatibilnost sa postojećim kodom. Omogućavanje ovih provjera pomaže da se ranije uhvate potencijalni problemi konkurencije, čineći prijelaz glatkim i sigurnijim. Kako ažurirate bazu kodova, možete početi da integrirate async/await sintax i druge funkcije Swift Concurrency postepeno bez potpunog prepisivanja. Some of the key problems Swift Concurrency addresses include: Rasni uslovi: Sprečavanje istovremenog pristupa zajedničkom mutibilnom stanju koje može uzrokovati nepredvidivo ponašanje. Callback pakao: Pojednostavljenje asinkronog koda koji se često oslanjao na vezane pozive ili upravljače završetkom, čineći kod lakšim za čitanje i održavanje. Kompleksnost upravljanja granicama: Odbacivanje kreiranja i sinhronizacije na niskoj razini, omogućujući programerima da se usredotoče na logiku umjesto na rukovanje granicama. Koordinacija istovremenih zadataka: Strukturirana istovremenost omogućava jasne hijerarhije zadataka uz pravilno otkazivanje i širenje grešaka. Koristeći nove jezične karakteristike kao što su Swift 6 pruža intuitivniji i robusniji način pisanja istovremenog koda, poboljšavajući produktivnost programera i stabilnost aplikacija. async/await Multitasking poslovi Suvremeni operativni sustavi i runtimes koriste multitasking da istovremeno izvršavaju jedinice posla. Swift Concurrency usvaja kooperativno multitasking, što se u osnovi razlikuje od preemptivnog multitasking modela koji se koristi od strane OS-level threadova. Razumijevanje razlike je ključ za pisanje performansi i bezbedan asincroni Swift kod. Preventivni multitasking Preventivni multitasking je model koji operativni sustavi koriste za upravljanje threadovima i procesima. U ovom modelu, sistemski rasporednik može prisilno prekinuti bilo koji thread u gotovo svakom trenutku kako bi izvršio kontekstni prebacivanje i dodelio CPU vrijeme drugom threadu. Preventivno multitasking omogućava istinsku paralelnost preko više CPU jezgre i sprečava pogrešno ponašanje ili dugotrajne žice od monopolizacije sistemskih resursa. Međutim, ova fleksibilnost dolazi uz trošak. Budući da žice mogu biti prekinute u bilo kojem trenutku u njihovom izvršenju – čak i usred kritične operacije – programeri moraju koristiti sinhronizacijske primitive kao što su muteks, semaphore ili atomske operacije kako bi zaštitili zajedničko varijabilno stanje. Ovaj model nudi veću kontrolu i sirovu istovremenost, ali takođe stavlja znatno veće opterećenje na programere. Osiguranje sigurnosti niti u preventivnom okruženju je sklono greškama i može dovesti do ne-determinističkog ponašanja - ponašanja koje varira od trčanja do trčanja - što je poznato teško razmotriti ili pouzdano testirati. Sa tehničke perspektive, preemptivno multitasking se oslanja na operativni sistem za rukovanje izvedenjem žica. OS može prekinuti žicu u gotovo svakom trenutku – čak i u sredini jedne funkcije – i prebaciti na drugu. Da bi to učinio, sistem mora izvršiti kontekstni prekidač, što uključuje čuvanje cijelog statusa izvršenja trenutnog žica (kao što su registri CPU-a, ukazivač uputa i ukazivač stack), i vraćanje prethodno sačuvano stanje drugog žica. Ovaj proces može takođe zahtijevati ispiranje CPU cache-a, onemogućavanje Translation Lookaside Buffer (TLB), i prijelaz između korisničkog načina i modela kernel. Svaki kontekstni prekidač zahtijeva vreme i troši sistemske resurse – pogotovo kada su kontekstni prekidači česti ili kada se mnoge žice takmiče za ograničene CPU jezgre. Iako ovaj model pruža maksimalnu fleksibilnost i istinsku paralelnost, često je prekomjeran za asincrone tokove posla, gdje zadaci obično provode većinu svog vremena čekajući I/O, korisnički unos ili mrežne odgovore umjesto da aktivno koriste CPU. Multitasking saradnja U ovom modelu, zadatak se pokreće dok dobrovoljno ne da kontrolu – obično na čekanju ili putem eksplicitnog poziva na Za razliku od tradicionalnih žica, kooperativni zadaci nikad nisu prisilno preopterećeni.To rezultira predvidljivom izvršenjem: kontekstni prekidači se javljaju samo na jasno definiranim točkama suspenzije. Task.yield() Swift-ove zadatke za saradnju planiraju se na lagani, upravljani putnim vremenom kooperativni niz žica – odvojen od Grand Central Dispatch redova. Očekuje se da će zadatci koji rade u ovom bazenu biti „dobri građani“, pružajući kontrolu kada je to prikladno, posebno tokom dugotrajnog ili CPU intenzivnog rada. kao ručna tačka suspenzije, osiguravajući da drugi zadaci imaju šansu za izvršenje. Task.yield() Međutim, kooperativno multitasking dolazi s upozorenjem: ako zadatak nikada ne obustavi, to može monopolizovati žicu na kojoj radi, odgađanje ili izgladnjivanje drugih zadataka u sustavu. U kooperativnom multitaskingu, temeljna jedinica izvršenja nije nit, već komad posla, često nazvan nastavak. Funkcija zaustavlja na , Swift runtime uhvaća trenutno stanje izvršenja u nastavak koji je raspodijeljen gomilom. Ovo nastavak predstavlja bod ponovnog pokretanja i prikazan je za buduće izvršenje. async await Umesto povezivanja niza sa dugotrajnim zadatkom, Swift runtime tretira niza kao vodič nastavaka. Svaka niza izvodi jedno nastavak za drugim. Kada se nastavak završi ili ponovo obustavi, niza preuzima sledeće spremno nastavak iz reda. As mentioned above, this model avoids traditional OS-level context switches. There is no need to save and restore CPU registers or thread stacks; the runtime simply invokes the next closure-like continuation. This makes task switching very fast and lightweight, though it involves increased heap allocations to store the suspended async state. Ključni kompromis: koristite malo više memorije, ali dobijate dramatično niži opseg za upravljanje zadatcima. Uvođenje na Zadatak Zadatak U konkurenciji, a pruža jedinicu asinkronog rada. Za razliku od jednostavnog pozivanja na Funkcija A je upravljani objekt koji se istovremeno pokreće s drugim zadacima u kooperativnom nizu žica. Task async Task 💡 Zadaci se upravljaju kooperativnim nizom žica. kooperativni niz žica je dizajniran za efikasno upravljanje konvergentnošću omogućujući zadatcima da isporuče CPU dok čekaju da se asinkronne operacije završe. 💡 Zadaci se upravljaju kooperativnim nizom žica. kooperativni niz žica je dizajniran za efikasno upravljanje konvergentnošću omogućujući zadatcima da isporuče CPU dok čekaju da se asinkronne operacije završe. Zadaće se mogu stvoriti da se istovremeno pokrenu, a mogu se takođe čekati ili otkazati. Oni pružaju finu kontrolu nad asinkronim ponašanjem i sastavni su deo strukturirane istovremenosti u Swift-u. Stvaranje a Task Zadatak se može stvoriti pomoću , koji odmah pokreće predviđenu asinkronu operaciju: Task Inicijator Inicijator Task(priority: .userInitiated) { await fetchData() } Kada kreirate A koristeći standardni inicijalizator (tj. ne ), ona nasljeđuje okolni kontekst aktera, prioritet, i zadatak-lokalne vrednosti. Ovo ponašanje je ključno za strukturiranu konvergentnost i sigurnost u konvergentnom kodu. Task odvojenost odvojenost 💡 Swift 6.2 uvodi značajnu promjenu u načinu na koji se rukuje konvergentnošću: podrazumevano, svi kodi se pokreću na MainActoru. Za pokretanje koda na pozadini, Swift 6.2 dodaje novi atribut @konkurentno. Možete koristiti i neizolirano ako kod ne zahtijeva pristup glavnom glumcu. WWDC Embracing Swift Concurrency 💡 Swift 6.2 uvodi značajnu promjenu u načinu na koji se rukuje concurrency: podrazumevano, svi kodovi se pokreću na MainActor Za pokretanje koda na pozadini, Swift 6.2 dodaje novi atribut @concurrent Također možete koristiti nonisolated ako kod ne zahtijeva pristup glavnom glumcu. WWDC Embracing Swift WWDC prihvata konkurenciju Swift WWDC prihvata konkurenciju Swift Pod poklopcem, u ranijim verzijama Swift Concurrency, Swift runtime koristio je unutarnji mehanizam nazvan Iako ovo svojstvo nije bilo deo javnog API-ja, igralo je ključnu ulogu u osiguravanju da zadaci stvoreni unutar koda izoliranog od glumaca budu izvršeni na istom glumcu, čuvajući bezbednost podataka. @_inheritActorContext Uz napredak u Swift, runtime je počeo tranziciju od Novi mehanizam poznat kao , koji je sada eksplicitnije rješava kompilera i runtime. @_inheritActorContext sending 💡 Šta je slanje? slanje je nova ključna reč uvedena u Swift 6 kao deo pomaka jezika ka sigurnijoj i eksplicitnijoj istovremenosti. Koristi se za označavanje parametara funkcija i vraćanje vrednosti koje se pomicaju preko granica istovremenosti. Posebno dobro radi na tipovima koji se ne mogu kopirati, osiguravajući sigurnost memorije i sprečavajući greške nakon upotrebe. func process(_ data: sending MyNonCopyableType) async { // `data` is moved here and can’t be used elsewhere after the call } 💡 Šta je slanje? slanje je nova ključna reč uvedena u Swift 6 kao deo pomaka jezika ka sigurnijoj i eksplicitnijoj istovremenosti. Koristi se za označavanje parametara funkcija i vraćanje vrednosti koje se pomicaju preko granica istovremenosti. Posebno dobro radi na tipovima koji se ne mogu kopirati, osiguravajući sigurnost memorije i sprečavajući greške nakon upotrebe. func process(_ data: sending MyNonCopyableType) async { // `data` is moved here and can’t be used elsewhere after the call } Kada pokrenete A , morate se pobrinuti da su sve vrednosti koje je zadatak uhvatio Kompilator sada primjenjuje ovo u vreme kompilacije koristeći Protokola i Funkcija tipa. Task.detached Sendable Sendable @Sendable Neuspeh da se uskladi may result in a compile-time error, particularly in strict concurrency mode. Sendable Zadaće takođe podržavaju prioritete, slično načinu na koji ih Grand Central Dispatch redovi rukuju. Uslovi Task Task.detached Kada radite sa Swift Concurrency, važno je razumjeti razliku između i , jer oni definišu kako i gde se izvodi asincroni rad. Task Task.detached Task Zadatak nasleđuje trenutni kontekst aktera (kao što je or any custom actor) and priority. It’s commonly used when you want to spawn a new asynchronous operation that still respects the current structured concurrency tree or actor isolation. This is especially useful for UI updates or working inside specific concurrency domains. Task MainActor Task { await updateUI() } In the example above, if called from the main actor, the će se takođe odvijati na glavnom glumcu, osim ako se izričito ne preseli na drugo mjesto. Task Task.detached Zadatak.detached creates a completely independent task. It doesn’t inherit the current actor context or priority. This means it starts in a global concurrent context and requires manage safety, especially when accessing shared data. Task.detached Task.detached { await performBackgroundWork() } Koristite kada je potrebno pokrenuti operacije u pozadini izvan trenutnog strukturiranog konteksta, kao što su dugotrajna izračunavanja ili izbjegavanje izolacije aktera. Task.detached Zajednički Thread Pool Cooperative Thread Pool u Swift Concurrency je mehanizam koji upravlja izvršenjem asinkronih zadataka tako što ih rasporedi na ograničen broj nitova, obično podudarajući se s brojem CPU jezgara. Cooperative Thread Pool u Swift Concurrency je mehanizam koji upravlja izvršenjem asinkronih zadataka tako što ih rasporedi na ograničen broj nitova, obično podudarajući se s brojem CPU jezgara. Swift Concurrency radi pomoću kooperativnog niza niza koji su dizajnirani za efikasno planiranje i minimalno nadređivanje niza. Za razliku od tradicionalnog modela izvođenja niza po zadatku, Swiftov pristup naglašava strukturiranu konvergentnost i planiranje svjesno resursa. A common oversimplification is to say that Swift Concurrency uses one thread per core, which aligns with its goal to reduce context switching and maximize CPU utilization. While not strictly false, this view omits important nuances about quality-of-service buckets, task priorities, and Darwin scheduler behavior. Thread Count: Nije tako jednostavno Thread Count: Nije tako jednostavno Na 16-core Mac-u, moguće je promatrati do 64 nitke koje upravlja samo Swift Concurrency - bez uključivanja GCD-a. Formalno za: Max threads = (CPU cores) × (dedicated quality-of-service buckets) Thus, on a 16-core system: 16 cores × 4 QoS buckets = 64 threads Svaki QoS bucket je u suštini namijenjen thread lane za grupu zadataka koji dijele sličan prioritet izvršenja. Ovi se upravljaju interno Darvinovim mehanizmom rasporeda thread i nisu isti kao GCD redovi. QoS kutije i prioritet zadatka QoS kutije i prioritet zadatka Iako Postoji šest konstanta, od kojih su neke aliase: TaskPriority Početna » Visoko Korisnost je niska podrazumevano → već prikazan na sredinu U pogledu jezgre, to pojednostavljuje na 4 nivoa glavnog prioriteta, svaki je mapiran u QoS bucket, što utiče na raspodjelu niza u kooperativnom niza. Kada se događa prekomjerno obavljanje poslova? Kada se događa prekomjerno obavljanje poslova? Pod normalnim opterećenjem, Swift Concurrency poštuje ograničenja kooperativnog bazena. Međutim, pod sukobom (npr. zadaci s visokim prioritetom koji čekaju na zadatke s niskim prioritetom), sistem može prekomjerno preuzeti teme kako bi sačuvao odgovornost. Ovo dinamičko podešavanje osigurava da zadaci osetljivi na vrijeme nisu blokirani na neodređeno vrijeme iza rada s nižim prioritetom. This behavior is managed by the Darwin kernel via Mach scheduling policies and high-priority linije - ne nešto što je izričito kontrolisano vašim kodom. pthreads Prioritet zadatka Swift pruža prioritetni sistem za zadatke, sličan Grand Central Dispatch (GCD), ali više semantički integrisan u strukturirani concurrency model. Inicijator za: Task Task(priority: .userInitiated) { await loadUserData() } Dostupni prioriteti su definisani od strane Uslovi korišćenja TaskPriority Priority Description / .high .userInitiated For tasks initiated by user interaction that require immediate feedback. .medium For tasks that the user is not actively waiting for. / .low .utility For long-running tasks that don’t require immediate results, such as copying files or importing data. .background For background tasks that the user is not directly aware of. Primarily used for work the user cannot see. • .high .userInitiated Za zadatke pokrenute interakcijom korisnika koji zahtevaju neposrednu povratnu informaciju. .medium For tasks that the user is not actively waiting for. • .low .utility Za dugotrajne zadatke koji ne zahtijevaju trenutne rezultate, kao što su kopiranje datoteka ili uvoz podataka. .background Za zadatke u pozadini o kojima korisnik nije izravno svjestan. Stvaranje zadataka s različitim prioritetima Stvaranje zadataka s različitim prioritetima Kada kreirate A unutar drugog zadatka (podrazumevano prioriteta), možete eksplicitno postaviti drugačiji prioritet za svaki ugrađeni zadatak. , a drugi je .high. Ovo pokazuje da se prioriteti mogu postaviti pojedinačno bez obzira na roditelja. Task .medium .low Task { // .medium by default Task(priority: .low) { print("\(1), "thread: \(Thread.current)", priority: \(Task.currentPriority)") } Task(priority: .high) { print("\(2), "thread: \(Thread.current)", priority: \(Task.currentPriority)") } } // 1, thread: <_NSMainThread: 0x6000017040c0>{number = 1, name = main}, priority: TaskPriority.low // 2, thread: <_NSMainThread: 0x6000017040c0>{number = 1, name = main}, priority: TaskPriority.high Ako izričito ne postavite prioritet za ugrađeni zadatak, on nasljeđuje prioritet od njegovog neposrednog roditelja. i Bloki nasljeđuju te odgovarajuće prioritete, osim ako nisu preopterećeni. .high .low Prioriteti zadataka mogu se naslijediti Prioriteti zadataka mogu se naslijediti Task { Task(priority: .high) { Task { print("\(1), "thread: \(Thread.current)", priority: \(Task.currentPriority)") } } Task(priority: .low) { print("\(2), "thread: \(Thread.current)", priority: \(Task.currentPriority)") Task { print("\(3), "thread: \(Thread.current)", priority: \(Task.currentPriority)") } Task(priority: .medium) { print("\(4), "thread: \(Thread.current)", priority: \(Task.currentPriority)") } } } // 2, thread: <_NSMainThread: 0x600001708040>{number = 1, name = main}, priority: TaskPriority.low // 1, thread: <_NSMainThread: 0x600001708040>{number = 1, name = main}, priority: TaskPriority.high // 3, thread: <_NSMainThread: 0x600001708040>{number = 1, name = main}, priority: TaskPriority.low // 4, thread: <_NSMainThread: 0x600001708040>{number = 1, name = main}, priority: TaskPriority.medium Ako izričito ne postavite prioritet za ugrađeni zadatak, on nasljeđuje prioritet od svog neposrednog roditelja. U ovom primeru, anonimni zadatci unutar blokova .high i .low nasljeđuju te odgovarajuće prioritete, osim ako nisu preopterećeni. Prioriteti eskalacije Prioriteti eskalacije Task(priority: .high) { Task { print("\(1), "thread: \(Thread.current)", priority: \(Task.currentPriority)") } await Task(priority: .low) { print("\(2), "thread: \(Thread.current)", priority: \(Task.currentPriority)") await Task { print("\(3), "thread: \(Thread.current)", priority: \(Task.currentPriority)") }.value Task(priority: .medium) { print("\(4), "thread: \(Thread.current)", priority: \(Task.currentPriority)") } }.value } // 1, thread: <_NSMainThread: 0x6000017000c0>{number = 1, name = main}, priority: TaskPriority.high // 2, thread: <_NSMainThread: 0x6000017000c0>{number = 1, name = main}, priority: TaskPriority.high // 3, thread: <_NSMainThread: 0x6000017000c0>{number = 1, name = main}, priority: TaskPriority.high // 4, thread: <_NSMainThread: 0x6000017000c0>{number = 1, name = main}, priority: TaskPriority.medium Ovaj mehanizam se zove prioritetna eskalacija – kada zadatak čeka zadatak s višim prioritetom, sistem može privremeno podići svoj prioritet kako bi izbjegao prepreke i osigurao odgovornost. Kao rezultat toga: Zadatak 2, koji je .low, se eskalira na .high dok se čeka. Zadatak 3, koji nema eksplicitni prioritet, nasljeđuje eskalirani prioritet od svog roditelja (Zadatak 2) i takođe se izvodi sa .highpriority. Zadatak 4 eksplicitno postavlja svoj prioritet na .medium, tako da na njega ne utječe eskalacija. Ne nasleđuje prioritet Zadatak.detached Zadatak.detached Uslovi korišćenja ( ) rade samostalno i ne nasljeđuju prioritet svog roditeljskog zadatka. Oni se ponašaju kao globalni zadaci sa svojim vlastitim rasporedom. Ovo je korisno za izoliranje pozadinskog rada, ali može dovesti i do neočekivanih neusklađenosti prioriteta ako se ne postavlja ručno. Task.detached Task(priority: .high) { Task.detached { print("\(1), "thread: \(Thread.current)", priority: \(Task.currentPriority)") } Task(priority: .low) { print("\(2), "thread: \(Thread.current)", priority: \(Task.currentPriority)") Task.detached { print("\(3), "thread: \(Thread.current)", priority: \(Task.currentPriority)") } Task(priority: .medium) { print("\(4), "thread: \(Thread.current)", priority: \(Task.currentPriority)") } } } // 1, thread: <NSThread: 0x60000174dec0>{number = 4, name = (null)}, priority: TaskPriority.medium // 2, thread: <_NSMainThread: 0x600001708180>{number = 1, name = main}, priority: TaskPriority.low // 3, thread: <NSThread: 0x60000174dec0>{number = 4, name = (null)}, priority: TaskPriority.medium // 4, thread: <_NSMainThread: 0x600001708180>{number = 1, name = main}, priority: TaskPriority.medium Tačke suspenzije i kako Swift upravlja Async izvršenjem U Swift, svaki poziv na Funkcija upotrebe je potencijalna tačka suspenzije - mjesto u funkciji gde izvršenje može da se zaustavi i nastavi kasnije.To je transformacija koja uključuje čuvanje stanja funkcije tako da se može nastaviti kasnije, nakon što se očekuje operacija završi. async await Here’s an example: func fetchData() async -> String { let result = await networkClient.load() return result } U ovom slučaju, Kada funkcija dostigne ovu liniju, može zaustaviti izvršenje, dati kontrolu sistemu i kasnije nastaviti jednom. finishes. Behind the scenes, the compiler transforms this function into a state machine that tracks its progress and internal variables. await networkClient.load() load() Pod kaputom: nastavci i državne mašine Svaki Funkcija u Swift-u je kompilirana u državnu mašinu. označava prijelaznu tačku. Prije nego što dostignete Za Swift: async await await Shrani trenutno stanje funkcije - uključujući lokalne varijable i trenutni pokazivač uputa. Suspenzira izvršenje i planira nastavak. Once the async operation completes, it resumes the function from where it left off. To je slično stilu kontinuiranog prolaza (CPS) koji se koristi u mnogim funkcionalnim programskim sistemima.U Swiftovom modelu konkordancije, ovo je orkestrirano internim tipovima kao što su i konkurencije runtime rasporeda. ParticialAsyncTask Suspenzija! = Blokiranje Kad ti nešto u Swift, trenutni thread nije blokiran, umjesto toga: await Trenutni zadatak vraća kontrolu izvršitelju Ostali zadaci mogu trčati dok čekaju Kada se očekivana operacija završi, suspendovani zadatak se nastavlja na odgovarajućem izvršitelju. Ovo čini u osnovi učinkovitiji i skalabilniji od blokiranih operacija na bazi žica kao što su . async/await DispatchQueue.sync Pustite druge zadatke da rade Task.yield() Uslovi korišćenja ( je statička metoda koju pruža Swift-ov concurrency sistem koji dobrovoljno obustavlja trenutni zadatak, dajući sistemu mogućnost da pokrene druge enqueued zadatke.To je posebno korisno u dugotrajnim asinkronim operacijama ili uskim krugovima koji prirodno ne sadrže tačke obustave. Task.yield() func processLargeBatch() async { for i in 0..<1_000_000 { if i % 10_000 == 0 { await Task.yield() } } } Bez , ovaj krug bi monopolizovao izvršitelja. periodično, sarađujete sa Swift-ovim istovremenim radnim vremenom, što vam omogućuje da održavate odgovornost i fer. await await Task.yield() Pod kapom Poziv čeka suspenzira trenutni zadatak i ponovno ga kvalificira na kraju reda za trenutnog izvršitelja (npr. glavnog igrača ili globalnog istovremenog izvršitelja). Task.yield() To je deo Swift-ovog kooperativnog multitasking modela: zadaci se pokreću do sljedeće tačke suspenzije i očekuje se da će donositi fer. Za razliku od preventivnih sistema (npr. žice), Swift zadaci se ne prekidaju silom – moraju dobrovoljno dati kontrolu. sažetak Swift 6 označava značajan korak naprijed u načinu na koji se rukuje konkurentnošću, nudeći programerima više kontrole, predvidljivosti i sigurnosti. Dok kurva učenja može biti strma na početku, razumijevanje tih koncepata otvara vrata za izgradnju visoko odgovornih i robustnih aplikacija. Dok nastavljamo da istražujemo dublje aspekte Swiftovog novog konkurentnog modela, jasno je da ove promjene polože temelje za budućnost sigurnog i skalabilnog razvoja aplikacija.