Я пришел сюда довольно комфортно с этими двумя понятиями, но с чем-то неясным для меня о них.
Прочитав некоторые ответы, я думаю, что у меня есть правильная и полезная метафора, чтобы описать разницу.
Если вы рассматриваете свои отдельные строки кода как отдельные, но упорядоченные игральные карты (остановите меня, если я объясню, как работают перфокарты старой школы), то для каждой отдельной написанной процедуры у вас будет уникальная стопка карт ( не копируйте и не вставляйте!) и разница между тем, что обычно происходит, когда код выполняется нормально и асинхронно, зависит от того, заботитесь вы об этом или нет.
Когда вы запускаете код, вы передаете ОС набор отдельных операций (на которые ваш компилятор или интерпретатор разбил ваш код «более высокого» уровня) для передачи процессору. С одним процессором, только одна строка кода может быть выполнена в любой момент времени. Таким образом, чтобы создать иллюзию одновременного запуска нескольких процессов, ОС использует технику, в которой она отправляет процессору только несколько строк из заданного процесса за раз, переключаясь между всеми процессами в соответствии с тем, как она видит. поместиться. В результате несколько процессов показывают прогресс конечному пользователю в одно и то же время.
Для нашей метафоры связь такова, что ОС всегда перетасовывает карты перед отправкой их в процессор. Если ваш стек карт не зависит от другого стека, вы не заметите, что ваш стек перестал выбираться, когда другой стек стал активным. Так что, если вам все равно, это не имеет значения.
Однако, если вам все равно (например, есть несколько процессов - или стопок карт - которые зависят друг от друга), то перетасовка ОС испортит ваши результаты.
Написание асинхронного кода требует обработки зависимостей между порядком выполнения независимо от того, чем в конечном итоге является этот порядок. Вот почему используются такие конструкции, как «обратные вызовы». Они говорят процессору: «Следующее, что нужно сделать, это рассказать другому стеку, что мы сделали». Используя такие инструменты, вы можете быть уверены, что другой стек получит уведомление, прежде чем он позволит ОС выполнить больше своих инструкций. («Если call_back == false: send (no_operation)» - не уверен, действительно ли это так, как это реализовано, но логически я думаю, что это согласованно.)
Для параллельных процессов разница в том, что у вас есть два стека, которые не заботятся друг о друге, и два рабочих для их обработки. В конце дня вам может понадобиться объединить результаты из двух стеков, что в свою очередь станет вопросом синхронности, но для выполнения вам снова все равно.
Не уверен, поможет ли это, но я всегда нахожу несколько полезных объяснений. Также обратите внимание, что асинхронное выполнение не ограничено отдельным компьютером и его процессорами. Вообще говоря, он имеет дело со временем или (в более общем смысле) порядком событий. Поэтому, если вы отправляете зависимый стек A на сетевой узел X, а его связанный стек B - на Y, правильный асинхронный код должен учитывать ситуацию, как если бы он выполнялся локально на вашем ноутбуке.