Dlaczego współbieżność?
Gdy tylko dodasz do aplikacji ciężkie zadania, takie jak ładowanie danych, spowalnia ona pracę interfejsu użytkownika lub nawet ją zawiesza. Współbieżność umożliwia wykonywanie 2 lub więcej zadań „jednocześnie”. Wadą tego podejścia jest bezpieczeństwo gwintów, które nie zawsze jest tak łatwe do kontrolowania. Na przykład, gdy różne zadania chcą uzyskać dostęp do tych samych zasobów, np. Próba zmiany tej samej zmiennej w różnych wątkach lub uzyskiwanie dostępu do zasobów już zablokowanych przez różne wątki.
Jest kilka abstrakcji, o których musimy wiedzieć.
- Kolejki.
- Synchroniczna / asynchroniczna wydajność zadań.
- Priorytety.
- Typowe problemy.
Kolejki
Musi być seryjny lub równoległy . A także globalne lub prywatne w tym samym czasie.
W przypadku kolejek szeregowych zadania będą kończone pojedynczo, podczas gdy w przypadku kolejek współbieżnych zadania będą wykonywane jednocześnie i będą kończone zgodnie z nieoczekiwanymi harmonogramami. Ta sama grupa zadań zajmie znacznie więcej czasu w kolejce szeregowej w porównaniu z kolejką współbieżną.
Możesz tworzyć własne kolejki prywatne (zarówno szeregowe, jak i współbieżne ) lub korzystać z już dostępnych kolejek globalnych (systemowych) . Kolejka główny jest jedynym seryjnym kolejka z wszystkich globalnych kolejek .
Zdecydowanie zaleca się, aby nie wykonywać ciężkich zadań, które nie są związane z pracą interfejsu użytkownika w głównej kolejce (np. Ładowanie danych z sieci), ale zamiast tego wykonywać je w innych kolejkach, aby interfejs użytkownika nie był zamrażany i reagował na działania użytkownika. Jeśli pozwolimy zmienić interfejs użytkownika w innych kolejkach, zmiany mogą zostać wprowadzone w innym i nieoczekiwanym harmonogramie i szybkości. Niektóre elementy interfejsu użytkownika można narysować przed lub po ich pojawieniu się. Może to spowodować awarię interfejsu użytkownika. Musimy również pamiętać, że skoro kolejki globalne są kolejkami systemowymi, system może na nich wykonywać inne zadania.
Jakość usług / priorytet
Kolejki mają również różne qos (Quality of Service), które ustawiają priorytet zadania (od najwyższego do najniższego):
.userInteractive - kolejka główna
.userInitiated - dla zadań inicjowanych przez użytkownika, na które użytkownik czeka na odpowiedź.
Użyteczność - dla zadań co zajmuje trochę czasu i nie wymaga natychmiastowej reakcji, np. praca z danymi
.background - dla zadań niezwiązanych z częścią wizualną, które nie są ściśle związane z czasem realizacji).
Istnieje również kolejka
.default, która nie przenosi informacji qos . Jeśli nie można było wykryć qos, toqos będzie używany między .userInitiated i .utility .
Zadania można wykonywać synchronicznie lub asynchronicznie .
Funkcja synchroniczna przywraca sterowanie do bieżącej kolejki dopiero po zakończeniu zadania. Blokuje kolejkę i czeka na zakończenie zadania.
Funkcja asynchroniczna zwraca sterowanie do bieżącej kolejki zaraz po wysłaniu zadania do wykonania w innej kolejce. Nie czeka na zakończenie zadania. Nie blokuje kolejki.
Typowe problemy.
Oto najpopularniejsze błędy popełniane przez programistów podczas projektowania aplikacji współbieżnych:
- Stan wyścigu - występuje, gdy działanie aplikacji zależy od kolejności wykonywania części kodu.
- Odwrócenie priorytetów - gdy zadania o wyższym priorytecie czekają na zakończenie zadań o mniejszym priorytecie z powodu zablokowania niektórych zasobów
- Deadlock - gdy kilka kolejek ma nieskończone oczekiwanie na źródła (zmienne, dane itp.) Już zablokowane przez niektóre z tych kolejek.
NIGDY nie wywołuj funkcji synchronizacji w głównej kolejce .
Jeśli wywołasz funkcję synchronizacji w głównej kolejce, zablokuje ona kolejkę, a kolejka będzie czekała na zakończenie zadania, ale zadanie nigdy nie zostanie ukończone, ponieważ nie będzie można go nawet uruchomić, ponieważ kolejka jest już zablokowane. Nazywa się to impasem .
Kiedy używać synchronizacji?
Kiedy musimy poczekać, aż zadanie zostanie zakończone. Fe, gdy upewniamy się, że jakaś funkcja / metoda nie jest wywoływana podwójnie. Mamy synchronizację i próbujemy zapobiec podwójnemu wywołaniu, dopóki nie zostanie całkowicie zakończona. Oto kod dotyczący tego problemu:
Jak dowiedzieć się, co spowodowało raport o awarii urządzenia z systemem IOS?
DispatchQueue.main.sync
z wątku w tle?