logo
0
читателей
Заметки о программировании. Как работает то, что ты щас закодил.  
О проекте Просмотр Уровни подписки Фильтры Статистика Обновления проекта Поделиться
Все проекты
О проекте
Когда пишешь код, бывает, ловишь себя на мысли, что ты погуглил и нашёл, как решить задачу, но понятия не имеешь, почему это решение работает. И, вроде бы, цель достигнута, но на душе некомфортно как-то. И хотел бы разобраться, но некогда, потому что задач таких ещё не одна, и не две. Так и жизнь проходит.
Знакомое чувство? ) Вот и мне тоже. Неизбежно пройдёт этап, когда жалко времени, чтобы получше разобраться в чём-то. Настанет этап, когда жалко времени разгребать костыли и кривые, ржавые велосипеды, чужие, и, особенно, свои.
В общем, предлагаю сделку. С меня - по возможности, просто, задорно и с огоньком рассказать о сложном, в контексте появления, особенностей развития той или иной технологии, её взаимосвязи с окружающими экосистемами, и, самое главное, того, что это нам даёт на практике. С вас - время на чтение, ну и подписка, если зайдёт.
Публикации, доступные бесплатно
Уровни подписки
Фильтры
Статистика
Обновления проекта
Контакты
Поделиться
Читать: 8+ мин
logo Заметки о программировании. Как работает то, что ты щас закодил.

Многопоточно: асинхронное синхронно

Да ‎простит‏ ‎меня ‎певец ‎Дима ‎Билан, ‎ведь‏ ‎название ‎этого‏ ‎поста‏ ‎есть ‎ничто ‎иное,‏ ‎как ‎аллюзия‏ ‎на ‎одну ‎из ‎его‏ ‎песен.‏ ‎Даа, ‎были‏ ‎времена...

Но ‎теперь‏ ‎серьёзно. ‎Многопоточность ‎и ‎асинхронность, ‎это‏ ‎мало‏ ‎того, ‎что‏ ‎разные ‎вещи,‏ ‎но ‎это ‎ещё ‎и ‎одно‏ ‎и‏ ‎то‏ ‎же. ‎Потому‏ ‎что ‎ни‏ ‎в ‎одном‏ ‎другом,‏ ‎возможно, ‎разделе‏ ‎знаний ‎о ‎программировании ‎нет ‎такой‏ ‎чудовищной ‎путаницы‏ ‎в‏ ‎терминах. ‎Разные ‎языки,‏ ‎разные ‎школы,‏ ‎разные ‎эпохи ‎использовали ‎и‏ ‎продолжают‏ ‎использовать ‎эти‏ ‎слова ‎в‏ ‎своих ‎целях, ‎наделяя ‎их ‎то‏ ‎одними,‏ ‎то ‎другими‏ ‎значениями. ‎Изначально,‏ ‎очень ‎давно, ‎многопоточность ‎была ‎изобретена‏ ‎для‏ ‎того,‏ ‎чтобы ‎выполнять‏ ‎программные ‎задачи‏ ‎асинхронно. ‎Но‏ ‎сейчас‏ ‎во ‎многих‏ ‎языках ‎уже ‎есть ‎более ‎современное‏ ‎понятие ‎асинхронности,‏ ‎которое‏ ‎не ‎является ‎классической‏ ‎многопоточностью, ‎но‏ ‎технически ‎опирается ‎именно ‎на‏ ‎неё.‏ ‎Тут ‎можно‏ ‎сломать ‎мозг,‏ ‎просто ‎поговорив ‎с ‎десятком ‎разных‏ ‎людей‏ ‎об ‎одном,‏ ‎казалось ‎бы,‏ ‎и ‎том ‎же: ‎каждый ‎будет‏ ‎понимать‏ ‎эту‏ ‎проблематику ‎по-своему.

Нам‏ ‎нужно ‎разобраться‏ ‎во ‎всём‏ ‎этом‏ ‎раз ‎и‏ ‎навсегда. ‎Что ‎такое ‎асинхронность? ‎А‏ ‎синхронность? ‎И‏ ‎если‏ ‎есть ‎многопоточность, ‎то‏ ‎должна ‎быть‏ ‎малопоточность, ‎или ‎как?

Терпение. ‎Начнём‏ ‎издалека,‏ ‎с ‎исторической‏ ‎справки. ‎Это,‏ ‎в ‎целом, ‎будет ‎общий ‎алгоритм‏ ‎рассмотрения‏ ‎тем ‎в‏ ‎данном ‎блоге‏ ‎(это ‎ведь ‎блог, ‎да? ‎[картинка‏ ‎с‏ ‎прекрасной,‏ ‎наивной ‎и‏ ‎такой ‎молодой‏ ‎Натали ‎Портман]).‏ ‎Известно,‏ ‎что ‎технологии‏ ‎развиваются ‎от ‎простого ‎к ‎сложному,‏ ‎и ‎каждый‏ ‎новый‏ ‎виток ‎обусловлен ‎либо‏ ‎ограничениями, ‎заложенными‏ ‎ранее, ‎либо ‎стремлением ‎эти‏ ‎ограничения‏ ‎разрушить. ‎Мало‏ ‎взять ‎актуальную‏ ‎картину ‎мира, ‎желательно ‎всегда ‎смотреть‏ ‎в‏ ‎корень, ‎с‏ ‎чего ‎всё‏ ‎начиналось, ‎и ‎тогда ‎станет ‎ясно,‏ ‎почему‏ ‎всё‏ ‎пришло ‎к‏ ‎тому, ‎что‏ ‎есть ‎на‏ ‎сегодняшний‏ ‎день. ‎Читайте‏ ‎внимательнее, ‎и ‎вы ‎увидите, ‎как‏ ‎кирпичики ‎будут‏ ‎ложиться‏ ‎один ‎к ‎одному,‏ ‎и ‎в‏ ‎итоге, ‎образуют ‎собой ‎причудливое‏ ‎знание.‏ ‎Здание. ‎Ну,‏ ‎не ‎важно.

На‏ ‎заре ‎компьютерной ‎эпохи, ‎перед ‎любыми‏ ‎вычислительными‏ ‎машинами ‎стояла‏ ‎ровно ‎одна‏ ‎задача: ‎выполнять ‎математические ‎расчёты ‎быстрее,‏ ‎точнее‏ ‎и‏ ‎стабильнее, ‎чем‏ ‎человек. ‎Нужно‏ ‎было ‎заменить‏ ‎толпу‏ ‎высокообразованных, ‎немношк‏ ‎медленных, ‎иногда ‎ошибающихся, ‎дорогих ‎специалистов‏ ‎по ‎вычислениям‏ ‎одним‏ ‎большим ‎железным ‎ящиком,‏ ‎который ‎делал‏ ‎бы ‎их ‎работу ‎лучше‏ ‎них.‏ ‎Пропустим, ‎наверное,‏ ‎эпоху ‎вычислительных‏ ‎машин ‎на ‎основе ‎электро-механических ‎реле‏ ‎и‏ ‎прочей ‎гериатрической‏ ‎техники, ‎и‏ ‎шагнём ‎сразу ‎в ‎электронную ‎эру,‏ ‎т.е.,‏ ‎конец‏ ‎40-х ‎годов‏ ‎XX ‎века,‏ ‎и ‎позже.‏ ‎По‏ ‎сути ‎своей,‏ ‎первые ‎ЭВМ, ‎это ‎были ‎улучшенные‏ ‎арифмометры: ‎они‏ ‎могли‏ ‎не ‎просто ‎складывать,‏ ‎вычитать, ‎умножать‏ ‎и ‎делить, ‎но ‎и‏ ‎выполнять‏ ‎эти ‎действия‏ ‎по ‎списку,‏ ‎одно ‎за ‎другим, ‎автоматически. ‎И‏ ‎ещё,‏ ‎ветвить ‎логику‏ ‎в ‎зависимости‏ ‎от ‎условий. ‎Роль ‎оператора ‎ЭВМ‏ ‎была‏ ‎в‏ ‎том, ‎чтобы‏ ‎составить ‎для‏ ‎машины ‎программу‏ ‎вычислений‏ ‎(или, ‎сокращённо,‏ ‎программу), ‎загрузить ‎в ‎"ящик" ‎(именно‏ ‎загрузить, ‎т.е.,‏ ‎положить‏ ‎внутрь ‎некий ‎физический‏ ‎носитель), ‎запустить‏ ‎процесс ‎(хотя ‎процессоров ‎сегодняшнего‏ ‎типа‏ ‎тогда ‎ещё‏ ‎и ‎не‏ ‎было), ‎получить ‎результаты, ‎и ‎далее‏ ‎как-то‏ ‎их ‎интерпретировать,‏ ‎согласно ‎постановке‏ ‎своей ‎исходной ‎задачи. ‎Физические ‎носители‏ ‎представляли‏ ‎собой‏ ‎так ‎называемые‏ ‎перфоленты ‎(ленты‏ ‎с ‎отверстиями,‏ ‎характер‏ ‎размещения ‎которых‏ ‎задавал ‎те ‎или ‎иные ‎операции),‏ ‎а ‎позже‏ ‎-‏ ‎перфокарты, ‎которые ‎уже‏ ‎хотя ‎бы‏ ‎не ‎рвались ‎в ‎ненужный‏ ‎момент.‏ ‎Устройство ‎"читало"‏ ‎ленты ‎и‏ ‎карты ‎последовательно, ‎и ‎выполняло ‎зашифрованные‏ ‎в‏ ‎них ‎машинные‏ ‎команды ‎(грубо‏ ‎говоря, ‎что ‎к ‎чему ‎прибавить,‏ ‎что‏ ‎отнять,‏ ‎и ‎пр.,‏ ‎только ‎на‏ ‎низком, ‎машинном‏ ‎уровне),‏ ‎модифицируя ‎рабочие‏ ‎данные, ‎и ‎переходило ‎к ‎следующему‏ ‎шагу. ‎Последовательно.‏ ‎То‏ ‎есть, ‎в ‎одном‏ ‎потоке ‎команд‏ ‎и ‎данных. ‎Одна ‎операция‏ ‎в‏ ‎единицу ‎времени.‏ ‎И ‎это‏ ‎именно ‎то, ‎что ‎было ‎тогда‏ ‎нужно.‏ ‎Естественно, ‎никаких‏ ‎языков ‎программирования,‏ ‎операционных ‎систем ‎и ‎всего ‎прочего‏ ‎тогда‏ ‎ещё‏ ‎не ‎было.‏ ‎Всё ‎максимально‏ ‎утилитарно: ‎засыпали‏ ‎кофейные‏ ‎зёрна, ‎получили‏ ‎молотый ‎кофе. ‎Это ‎и ‎есть‏ ‎синхронность, ‎как‏ ‎её‏ ‎понимают ‎в ‎ИТ.

Но‏ ‎вообще, ‎тут‏ ‎надо ‎бы ‎оговориться. ‎Все‏ ‎мы‏ ‎знаем, ‎что‏ ‎есть, ‎например,‏ ‎синхронное ‎плавание. ‎Или, ‎вот, ‎военные‏ ‎идут‏ ‎строем ‎во‏ ‎время ‎парада‏ ‎- ‎они ‎движутся ‎абсолютно ‎синхронно.‏ ‎Или,‏ ‎плывёт‏ ‎косяк ‎рыбок‏ ‎в ‎океане,‏ ‎и ‎вдруг‏ ‎все‏ ‎они ‎синхронно‏ ‎меняют ‎направление. ‎Тут ‎можно ‎было‏ ‎бы ‎подумать,‏ ‎что‏ ‎синхронность, ‎это ‎когда‏ ‎несколько ‎разных‏ ‎объектов ‎совершают ‎действия ‎одновременно,‏ ‎т.е.,‏ ‎имеется ‎не‏ ‎один ‎поток‏ ‎вычислений, ‎а ‎множество. ‎Но: ‎в‏ ‎программировании,‏ ‎это ‎не‏ ‎так. ‎Нужно‏ ‎просто ‎запомнить, ‎что ‎синхронно ‎-‏ ‎это‏ ‎последовательно,‏ ‎а ‎не‏ ‎параллельно. ‎И,‏ ‎стало ‎быть,‏ ‎наоборот.

Технический‏ ‎прогресс ‎неумолим‏ ‎и ‎беспощаден. ‎На ‎смену ‎радиолампам‏ ‎пришли ‎транзисторы.‏ ‎Громадные‏ ‎конструкции ‎из ‎проводов,‏ ‎катушек, ‎реле,‏ ‎металлических ‎шкафов ‎уступили ‎место‏ ‎миниатюрным‏ ‎интегральным ‎схемам‏ ‎на ‎полупроводниках.‏ ‎Компьютеры ‎становились ‎всё ‎меньше ‎и‏ ‎экономичнее,‏ ‎мощнее, ‎и‏ ‎в ‎то‏ ‎же ‎время ‎дешевле. ‎Ну ‎и‏ ‎бла,‏ ‎бла,‏ ‎бла, ‎в‏ ‎итоге ‎люди‏ ‎поняли, ‎что‏ ‎им‏ ‎тесна ‎изначальная‏ ‎парадигма ‎последовательного ‎выполнения ‎операций. ‎Почему‏ ‎нельзя ‎их‏ ‎делать‏ ‎параллельно, ‎или ‎хотя‏ ‎бы ‎как-то‏ ‎имитировать ‎это ‎для ‎внешнего‏ ‎мира?‏ ‎Ведь ‎использовать‏ ‎один ‎компьютер‏ ‎для ‎решения ‎нескольких ‎задач ‎одновременно,‏ ‎это‏ ‎эффективнее, ‎чем‏ ‎использовать ‎одновременно‏ ‎несколько ‎компьютеров, ‎каждый ‎для ‎решения‏ ‎одной‏ ‎задачи.‏ ‎Это ‎просто‏ ‎намного ‎дешевле‏ ‎должно ‎быть.‏ ‎Это‏ ‎надо ‎было‏ ‎изобрести, ‎т.к. ‎игра ‎явно ‎стоила‏ ‎свеч.

Думаю, ‎пора‏ ‎очертить‏ ‎примерный ‎круг ‎вопросов,‏ ‎проблем ‎и‏ ‎их ‎решений, ‎которые ‎будут‏ ‎затронуты‏ ‎в ‎дальнейших‏ ‎постах ‎по‏ ‎данной ‎тематике.

1. Устройство ‎микропроцессора. ‎Как ‎физически‏ ‎происходит‏ ‎обработка ‎сигналов.‏ ‎Зачем ‎в‏ ‎процессоре ‎столько ‎транзисторов, ‎и ‎что‏ ‎ещё‏ ‎там‏ ‎есть. ‎Как‏ ‎внутри ‎него‏ ‎представлены ‎данные,‏ ‎что‏ ‎значит ‎их‏ ‎обработка. ‎При ‎чём ‎тут ‎конвейер,‏ ‎что ‎такое‏ ‎регистры.‏ ‎Что ‎такое ‎кэш‏ ‎уровней ‎1‏ ‎и ‎2, ‎и ‎почему‏ ‎производители‏ ‎гордятся ‎их‏ ‎размером, ‎но‏ ‎слишком ‎много ‎памяти ‎туда ‎не‏ ‎припаивают‏ ‎всё ‎равно.‏ ‎Что ‎такое‏ ‎контекст ‎(исполнения), ‎как, ‎когда ‎и‏ ‎зачем‏ ‎осуществляется‏ ‎его ‎переключение.‏ ‎Что ‎такое‏ ‎ядро ‎(core),‏ ‎и‏ ‎что ‎такое‏ ‎поток ‎(thread), ‎и ‎в ‎каких‏ ‎они ‎отношениях.‏ ‎Циклы,‏ ‎такты, ‎генератор ‎частоты,‏ ‎машинные ‎команды,‏ ‎прерывания, ‎Винни ‎Пух ‎и‏ ‎все-все-все.

2. Операционная‏ ‎система. ‎Что‏ ‎такое ‎процесс,‏ ‎и ‎как ‎он ‎связан ‎с‏ ‎программой.‏ ‎Потоки ‎(вот!‏ ‎началось! ‎потоки‏ ‎уже ‎были, ‎и ‎тут ‎снова‏ ‎они,‏ ‎но‏ ‎в ‎другом‏ ‎смысле). ‎Выполнение‏ ‎нескольких ‎потоков‏ ‎на‏ ‎одном ‎физическом‏ ‎ядре ‎процессора. ‎И, ‎наоборот, ‎работа‏ ‎с ‎многоядерными‏ ‎процессорами‏ ‎("много", ‎это ‎не‏ ‎только ‎2‏ ‎или ‎4, ‎но ‎и‏ ‎64‏ ‎или, ‎скажем‏ ‎4 ‎CPU‏ ‎по ‎64 ‎ядра). ‎Системные ‎средства‏ ‎взаимодействия‏ ‎потоков ‎и‏ ‎процессов. ‎Разделяемые‏ ‎ресурсы ‎операционной ‎системы. ‎Обзор ‎эволюции‏ ‎операционных‏ ‎систем‏ ‎от ‎состояния‏ ‎"предоставляю ‎аппаратные‏ ‎ресурсы ‎по‏ ‎требованию‏ ‎программ" ‎к‏ ‎состоянию ‎"сама ‎решаю, ‎какую ‎программу‏ ‎когда ‎выполнять,‏ ‎и‏ ‎обеспечиваю ‎процесс ‎переключения".

3. Многопоточное‏ ‎программирование. ‎Цели,‏ ‎ради ‎которых ‎надо ‎было‏ ‎так‏ ‎всё ‎усложнять.‏ ‎Трудности ‎синхронизации‏ ‎потоков ‎(в ‎смысле, ‎синхронизации? ‎они‏ ‎же‏ ‎параллельные?). ‎Конкуренция‏ ‎за ‎ресурсы,‏ ‎обеспечение ‎целостности ‎данных. ‎Проблемы ‎производительности.‏ ‎Утрата‏ ‎управляемости.‏ ‎Методики ‎избежания‏ ‎проблем ‎путём‏ ‎создания ‎других‏ ‎проблем.‏ ‎Бег ‎по‏ ‎граблям, ‎задорные ‎конкурсы, ‎и ‎возврат‏ ‎к ‎началу‏ ‎эволюции.‏ ‎Разница ‎между ‎работой‏ ‎с ‎многопоточностью‏ ‎в ‎настольных ‎однопользовательских ‎приложениях‏ ‎и‏ ‎в ‎клиент-серверных‏ ‎системах, ‎ориентированных‏ ‎на ‎массовую ‎обработку ‎одновременных ‎внешних‏ ‎запросов.

4. Понятие‏ ‎асинхронности. ‎Главное‏ ‎идейное ‎отличие‏ ‎от ‎многопоточности. ‎Идейные ‎сходства. ‎Вывод‏ ‎о‏ ‎том,‏ ‎что ‎это‏ ‎всё-таки ‎не‏ ‎одно ‎и‏ ‎то‏ ‎же. ‎Выяснение‏ ‎вопроса, ‎при ‎чём ‎здесь ‎таймеры‏ ‎и ‎машина‏ ‎статусных‏ ‎переходов, ‎аппаратные ‎прерывания‏ ‎и ‎переключение‏ ‎контекста ‎исполнения ‎машинных ‎команд.‏ ‎Почему‏ ‎неблокируемые ‎вызовы‏ ‎на ‎самом‏ ‎деле ‎блокируются, ‎но ‎не ‎в‏ ‎том‏ ‎смысле, ‎как‏ ‎некоторые ‎думают.‏ ‎Ключ ‎к ‎масштабируемости: ‎как ‎асинхронность‏ ‎позволяет‏ ‎выжимать‏ ‎из ‎оборудования‏ ‎всё ‎и‏ ‎откладывать ‎модернизацию‏ ‎ИТ-инфраструктуры‏ ‎веб-приложений ‎до‏ ‎лучших ‎времён. ‎Вообще, ‎по ‎опыту,‏ ‎нередко ‎именно‏ ‎понятие‏ ‎асинхронности ‎даётся ‎людям‏ ‎наиболее ‎тяжело.‏ ‎Этим ‎постом ‎мы ‎должны‏ ‎расставить‏ ‎все ‎точки‏ ‎над ‎i.

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

Что ‎ж, ‎удачи‏ ‎нам. ‎Она‏ ‎понадобится.

Обновления проекта

Статистика

Фильтры

Подарить подписку

Будет создан код, который позволит адресату получить бесплатный для него доступ на определённый уровень подписки.

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

Будет создан код, который позволит адресату получить сумму на баланс.

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

Добавить карту
0/2048