Всем привет. В этом видео мы начнем рассказывать о многопоточности и ее использовании в приложении. И прежде, чем говорить о многопоточности необходимо дать несколько определений, которые мы будем использовать. Процесс - это экземпляр компьютерной программы, которая выполняется, он содержит программный код и его текущую деятельность. Поток - это наименьшая последовательность запрограммированных команд, которые могут управляться независимо планировщиком, который обычно является частью операционной системы. Задача - абстрактная концепция работы которая должна быть выполнена. Многопоточность - модель программирования, и исполнение кода позволяет нескольким потокам выполняться в рамках одного процесса приложения. Все потоки находятся в одном адресном пространстве, делят одну и ту же виртуальную память, и имеют те же права доступа что и процесс приложения. В любом приложении есть как минимум один поток, этот поток называется главным. Он создается операционной системой и запускается при старте приложения. В главном потоке выполняются важные задачи такие как: обновление пользовательского интерфейса, и реагирование на события взаимодействия с пользователем. Наша задача как разработчиков держать главный поток свободным от задач, требующих большого времени исполнения. Для того чтобы написанный вами исходный код мог быть запущен на устройстве, компилятор преобразует его в машинный код, который представляет собой систему интерпретирующийся процессором. Затем, этот код упаковывается внутри приложения вместе с ресурсами и другими данными. Когда пользователь запускает это приложение на IOS устройстве, этот код загружается в память и CPU выполняет его инструкцию за инструкцией. Одно ядро CPU выполняет только одну инструкцию в единицу времени, применением многоядерных CPU позволило реализовать механизм распараллеливание задач, позволяющий выполнять несколько задач на разных потоках одновременно. В данной технологии каждый поток может выполняться в отдельном ядре. Однако если CPU является одноядерным или другие ядра заняты и не могут выполнять код нашего приложения, применяется другой подход называемый Context switch. Ядро CPU запускает один поток на какое-то время, выполняет его, затем переключается на другой поток и выполняет его, и так до тех пор пока все инструкции в каждом потоке не будут выполнены. У потоков есть приоритеты, назначаемые операционной системой. Эти приоритеты влияют, но не являются единственным фактором того как часто CPU будет переключаться на поток, и как долго он будет выполнять инструкции этого потока. Чем выше приоритет потока, тем чаще CPU будет переключаться на этот поток и тем дольше будет выполнять его команды. Таким образом возможные ситуации, когда потоки с очень низким приоритетом могут выполняться крайне редко или не выполняться совсем до тех пор пока не завершатся потоки с более высоким приоритетом. Давайте представим такую ситуацию, что вы разрабатываете приложение в котором требуется загрузить большой объем данных из интернета, например, видео или большое изображение, и затем отобразить их в пользовательском интерфейсе. Если в нашем приложении есть только один главный поток, то он должен выполнять всю работу, отрисовывать интерфейс, обеспечивать взаимодействие с пользователем, отправлять сетевые запросы и многое другое. Как и любой другой поток, главный поток умеет выполнять задачи только последовательно, одна за другой, и если он выполняет какую-то отнимающую много времени задачу, другие задачи вынуждены ожидать ее завершения прежде, чем они начнут обрабатываться на главном потоке. Можно сказать, что главный поток блокируется на время выполнения такой задачи. Поскольку в IOS обновление интерфейса и взаимодействие с пользователем разрешены только из главного потока, его блокировка приводит к тому, что поток перестает обновлять интерфейс или отвечать на команды пользователя. Это плохо, поскольку пользователь может решить, что ваше приложение зависло и закрыть его или вовсе удалить. Как этого избежать. Просто переместите выполнение загрузки этих данных, на другой, на фоновый поток, оставив главный поток доступным для отображения пользовательского интерфейса и реагирования на действия пользователя. После завершения загрузки данных в фоновом потоке, необходимо будет обновить пользовательский интерфейс на главном, использовании многозадачности в приложение предоставляет два очень важных потенциальных преимущества, улучшает реакцию восприятия приложения. Как мы уже говорили ранее, вынесение длительных по времени исполнения задач в отдельный поток, помогает разгрузить главный поток, оставив его свободным для обработки задач связанных с обновлением пользовательского интерфейса и взаимодействием с пользователем. Так же позволяет улучшить производительность приложений на многоядерных системах, за счет распараллеливании потоков. Как мы говорили ранее, при использовании параллелизма на многоядерных CPU, каждый поток может выполняться в отдельном ядре. Это позволяет нам разбить сложные вычисления на несколько маленьких отдельных вычислений, которые могут быть запущены параллельно на разных потоках, что в итоге позволяет сократить общее время вычисления. Так же с распараллеливанием связаны некоторые проблемы, например, наличие нескольких потоков выполнения в приложении может значительно усложнить код, проблема обеспечения доступа к общим ресурсам. Как только мы позволяем заданиям работать параллельно, появляются проблемы связанные с тем, что разные потоки захотят получить доступ к одним и тем же ресурсам, например, захотят изменять одну и ту же переменную или захотят получить доступ к уже заблокированным ресурсам. Это может привести к разрушению самих ресурсов используемых операциями на других потоках, также может привести к возникновению deadlock, ситуации, когда потоки будут находиться в ожидании ресурсов занятых этими же потоками. Возникновение livelock, ситуации, когда потоки заняты выполнением ненужной работы или возникновению "состояния гонки" (race conditions). Ситуации, когда очередность выполнения задач нарушается, что приводит к нарушению работы логики приложения. Так же использованием многопоточности может привести к возникновению инверсии приоритетов. Ситуации когда потоки с низким приоритетом вытесняют потоки с более высоким приоритетом. Теперь мы немного коснемся технологий с которыми вам предстоит познакомиться в рамках данного курса. В разработке IOS приложений для реализации многопоточности, Apple предлагает нам использовать следующие инструменты, Threading, Grand Central Dispatch (GCD) и Operation. Технология Threading, ветвление, сейчас используются довольно редко, так как является низкоуровневым механизмом, сложным и неудобным в применении. Поэтому в рамках данного курса мы будем ее рассматривать только поверхностно. Более подробно в учебном блоке мы будем изучать технологию Grand Central Dispatch, диспетчер потоков и Operation (операция), широко используемых в настоящее время, мы также будем говорить с вами об очередях выполнения задач, последовательных и параллельных. Потоков безопасности, а также проблемах с которыми вы можете столкнуться применяя данные технологии, такими как deadlock, livelock, race conditions и инверсия приоритетов.