В современном мире нет такой вещи, как однозадачность. Мы всегда многозадачны в нашей жизни, я пишу эту статью и слушаю музыку. Так как же компьютеры и смартфоны, неотъемлемая часть нашей жизни, могут выполнять только одну задачу. И к нашему облегчению, это не так!

Много раз вы открываете свой телефон и просматриваете что-то в Интернете, и вдруг появляется уведомление, как будто кто-то только что написал вам сообщение. В фоновом режиме ваши приложения обновляются одновременно. И ваш Gmail также уведомляет вас, что кто-то только что отправил вам письмо. Вы когда-нибудь задумывались, как происходит эта многозадачность, когда вы взаимодействуете только с одним приложением на переднем плане. Это все из-за функций MultiThreading и MultiProcessing.

Прежде чем идти дальше, я хотел бы познакомить вас с некоторыми основными терминами, которые мы будем здесь использовать:

  • Процесс: это просто выполняемая программа. Как и ваше приложение GMail, которое ищет новые электронные письма, это процесс, который в настоящее время выполняется в фоновом режиме.
  • Поток: это наименьшая единица, которая является частью процесса, который может выполняться независимо. Да, верно, это часть процесса, несколько потоков могут принадлежать одному и тому же процессу.

Прежде чем перейти к концепции многопоточности и многопроцессорности, сначала давайте рассмотрим многозадачность:

Более десяти лет назад в наших системах обычно использовался один процессор. Но и в ту эпоху наши компьютеры выполняли несколько задач одновременно. Он был основан на явлении, называемом «переключение контекста». Предположим, вы хотите проигрывать музыку во время работы над заданием в документе Word. Что сделало наше ядро, так это то, что оно сначала выделило ЦП для 1 процесса (скажем, P1). Когда этот процесс (P1) ждал какой-либо задачи ввода-вывода, вместо того, чтобы тем временем оставлять ЦП бездействующим, ядро ​​​​просто переключало контекст и передало ЦП другому процессу (P2). Когда процесс P1 выполняет ввод-вывод, он ждет своей очереди, чтобы получить ЦП, и когда P2 хочет выполнить какую-либо задачу ввода-вывода, ядро ​​просто возвращает ЦП P1. Переключение контекста происходит настолько быстро (в миллисекундах), что мы никогда не почувствуем этого невооруженным глазом. И вот как, работа была сделана.

Это то же самое, что явление, на котором сделаны мультфильмы. Они также представляют собой набор изображений персонажей, но они меняются местами так быстро, что невооруженным глазом кажется, что персонажи действительно взаимодействуют.

Теперь, в современном мире, у нас есть мультипроцессоры (несколько ЦП), и даже один процессор имеет несколько ядер. Итак, теперь предположим, что у вас есть 4 процесса, которые вы хотите запустить в своей системе одновременно, и ваша система имеет 2 процессора, 2 процессора будут совместно использоваться 4 процессами по очереди. Предположим, что сначала P1 и P2 выделяются оба процессора, когда любой из них ожидает выполнения некоторой задачи ввода-вывода, вместо того, чтобы оставлять освобожденный ЦП бездействующим, процессу P3 выделяется освобожденный процессор. Таким образом, цикл продолжается, и это явление называется Многопроцессорность.

Теперь каждый процесс имеет тенденцию делегировать свою работу своим дочерним процессам, которые также известны как потоки. Эти потоки работают параллельно друг с другом и совместно используют общий исполняемый код и пространство памяти. Эти потоки могут работать независимо без необходимости в других потоках. Эти потоки также являются своего рода процессом, просто немного облегченным. Так что здесь тоже самое явление переключения контекста между потоками. Среди потоков ЦП делится на небольшие кванты времени. Как и в случае с двумя потоками, каждый поток будет обращаться к ЦП в течение определенного времени (квант), а затем позволить другому потоку использовать ЦП, пока он ждет. Это явление называется Многопоточность.

На данный момент у вас может возникнуть сомнение, что если многопоточность и многопроцессорность основаны на одном и том же явлении совместного использования ЦП, зачем тогда мне нужна многопоточность?

Предположим, у вас есть приложение с графическим интерфейсом, которое загружает изображение одним нажатием кнопки. Вы загружаете большое изображение, и пока это изображение не будет загружено, ваше приложение с графическим интерфейсом останется без ответа, если только мы не загрузим файл в отдельном потоке выполнения. Это большое преимущество многопоточных систем.

Хотя при управлении потоками возникает дополнительная проблема, поскольку вам необходимо убедиться, что критическая часть выполнения выполняется изолированно, без вмешательства других потоков. Позвольте мне объяснить вам это на примере, предположим, что у вас есть банковская система банкоматов, которая помогает клиенту снимать наличные. И есть клиент, скажем С, у которого на счету 1000 рупий. И ваш код для вывода выглядит примерно так:

function withdraw( amount) {

    fetch balance;                       // Line 1

    if(balance > = amount) {            // Line 2
        balance = balance - amount;     // Line 3
    }

    save balance;                       // Line 4
}

Предположим, клиент одновременно инициирует 2 запроса на снятие средств, по 500 и 800 рупий. Оба этих запроса создали 2 разных потока (скажем, W1 и W2), и оба начали выполняться в одно и то же время, и оба получили «баланс», который в настоящее время составляет 1000. , и теперь находятся в строке 2. Поскольку сейчас баланс составляет 1000, а обе суммы 800 и 500 являются меньшими суммами, это позволит выполнить код, и клиент сможет снять 1300 рупий, больше, чем его баланс. Очевидно, у нас есть некоторая ошибка в нашем коде. Обычно эта синхронизация потоков решается с помощью примитивов ОС, таких как мьютексы и семпафоры. Нам нужно было бы что-то сделать с нашим кодом, чтобы строки 1–4 выполнялись за один раз, и между этими строками в настоящее время находится только один поток.

Ну это все. В основном мы используем концепции многопоточности и многопроцессорности для ускорения нашей работы, поэтому наш процессор никогда не простаивает, пока так много работы.