Параллельный -0-синхронный/асинхронный/блокирующий/неблокирующий/процесс/поток

задняя часть

Синхронные, асинхронные, блокирующие, не блокирующие, эти четыре концепции очень мало людей могут четко сказать, не верьте в это, вы можете сначала попытаться записать

синхронный и асинхронный

关注维度:消息的通信机制(synchronous communication/asynchronous communication)

判断标准:调用者是否主动等待被调用者的返回结果

同步的理论说明:任务A的执行过程中调用了任务B。任务A对任务B发起调用后,主动等待调用结果。

同步的生活举例:你去书店问老板,是否有《操作系统》这本书,老板说:稍等,我查一下。然后开始查啊查,等查好了,告诉你结果(主动等待被调用方返回结果)。

异步的理论说明:任务A的执行过程中调用了任务B。任务A对任务B发起调用后,继续执行后续工作。任务B完成后通过状态、通知来通知调用者。

异步的生活举例:你去书店问老板,是否有《操作系统》这本书,查好了打电话给你,然后直接挂电话了(此时被调用方不返回结果)。过了几天,查好了,老板主动打电话给你(被调用方回调调用方,告知结果)。

блокирующий и неблокирующий

关注维度:任务在等待调用结果时的状态

判断标准:调用方在等待被调用方的返回结果时,是否可以做其他事(是否被挂起)

阻塞的理论说明:任务A对任务B发起调用后,任务B需要执行一段时间才可返回结果,任务A选择等待任务B的返回结果(暂时挂起)。

阻塞的生活举例:你去书店问老板,是否有《操作系统》这本书,你会一直把自己挂起,什么是后不干,一直在那等,直到得到返回结果。

非阻塞的理论说明:任务A对任务B发起调用后,与此同时,任务A在任务B执行的过程中去完成别的工作,等待任务B结果返回后再继续(不挂起,而是继续执行自己的任务)。

非阻塞的生活举例:你去书店问老板,是否有《操作系统》这本书,不管老板有没有告诉你,你自己都先去玩了(继续执行自己的任务而不是干等),但是也要偶尔也要check一下老板是否有了结果。

Мы рассматриваем пользовательский поток как вызывающую программу, а поток ядра — как вызываемую и описываем несколько моделей ввода-вывода текущего процесса с помощью нескольких изображений и простых примеров кода:

Синхронный блокирующий ввод-вывод:

read(socket, buffer)
process(buffer)

Синхронный неблокирующий ввод-вывод:

while(read(socket,buffer) != SUCCESS);
process(buffer);

Мультиплексирование ввода-вывода:

select(socket);
while(1){
    sockets = select();
    for(socket in sockets){
        if(canRead(socket)){
            read(socket,buffer);
            process(buffer);
        }
    }
}

Хотя этот метод позволяет обрабатывать несколько запросов ввода-вывода в одном потоке, процесс каждого запроса ввода-вывода по-прежнему блокируется, а среднее время даже больше, чем в модели синхронного блокирующего ввода-вывода.

Реакторный режим:

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

UserEventHandler handleEvent(){
    if(canRead(socket)){
        read(socket,buffer);
        process(buffer);
    }
}

Reactor.register(new UserEventHandler(socket));

Reactor.epollHandleEvents(){
    while(1){
        sockets = select();
        for(socket in sockets){
            getEventHandler(socket).handleEvent();
        }
    }
}

Мультиплексирование ввода-вывода по-прежнему использует системный вызов select, который блокирует поток.В лучшем случае его можно рассматривать только как асинхронный блокирующий ввод-вывод, а не настоящий асинхронный ввод-вывод.

Асинхронный неблокирующий ввод-вывод:

При асинхронном блокирующем вводе-выводе пользовательский поток считывает и обрабатывает данные самостоятельно после получения уведомления. В асинхронном неблокирующем вводе-выводе, когда пользовательский поток получает уведомление, данные подготовлены, и пользовательский поток может использовать их напрямую (процесс чтения данных опущен)

UserCompeletionHandler.handleEvent(buffer){ process(buffer); }

aioRead(socket, new UserCompeletionHandler());

Что это за процесс:

计算机最初发明的初衷是用于解决耗时耗力的复杂计算,是一个计算器

最原始的计算机执行程序的过程如下:等待用户输入指令->用户输入->计算机操作->等待用户输入指令->用户输入->计算机操作。在用户思考或者输入的过程中,计算机就空闲下来。

后来有了批处理系统,用户可以把许多指令(如输入1,输入2)写在磁盘中,计算机的执行过程变为:用户输入指令集合->取指令->执行->取指令->执行。        

批处理系统大大提高了便捷性,但是还是存在一个问题,假设指令集合中有A,B两个程序,当程序A进行I/O处理时,程序B只能等待程序A直到其运行完。也就是说,内存中只能有一个程序在执行。

           |程序One|程序Two|    计算机中有两个程序

Time1:     |内存|              内存中装载程序One

Time2:             |内存|      内存中装载程序Two

那么,如何在内存中装入多个程序呢?于是人们发明了进程,每个在运行的程序都看做一个进程,给每个进程分配合适大小的对应的内存地址空间,进程之间的空间互不干扰,并且保存每个进程的运行状态。通过进程之间的相互切换,使计算机看起来在一段时间内有几个程序在同时执行。   
           |程序One|程序Two|    计算机中有两个程序

Time1:    |部分内存|部分内存|    内存中装载程序One,Two,分别在不同的部分。

进程让程序之间的并发成为了可能,从宏观上看,某个时间段内有多个程序在同时执行,但实际上在某一时刻只有一个程序(一部分的内存)会得到CPU,进行执行。

Что такое нить:

进程让程序之间的并发成为了可能,我们可以在电脑上同时听歌,打字了(两个不同的程序之间切换)。

Но требования людей к производительности программ в реальном времени становятся все выше и выше. Например, для QQ Music нужно не только обрабатывать интерактивные запросы, отправленные пользователями, но и воспроизводить песни. Предполагая, что QQ Music воспроизводит песню в определенный момент, вы нажимаете кнопку «пауза», и вам нужно дождаться окончания песни перед обработкой операции «пауза».

Таким образом, люди разбили процесс, соответствующий программе QQ Music, на несколько потоков. Есть потоки для воспроизведения песен и потоки для обработки интерактивных запросов. Каждый поток отвечает за независимую подзадачу. В данном случае мы нажали кнопку «пауза», QQ Music освобождает поток, который приостанавливает воспроизведение песни, позволяет потоку интерактивного запроса обработать запрос пользователя, а затем переключается обратно после ответа, так что поток, воспроизводящий песню, получает ЦП. Конкретный процесс выглядит следующим образом:

 播放线程---------------------挂起`````````````````播放线程----------     

                  用户点击暂停

                                  交互线程--------处理完毕
线程让进程内的子任务并发成为了可能。

3. Программа, процесс, поток:

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

Процессы делают возможным параллелизм между программами, а потоки делают возможным параллелизм подзадач внутри процесса.