Рубрики
Без рубрики

Топ 5 Вопросы собеседования параллелизма для инженеров программного обеспечения

Практикуйте эти 5 вопросов, и вы получите доверие к любому вопросу интервью-интервью. Помечено карьеру, Python, Csharp, Java.

(Некоторым фоном: я опросил сотни кандидатов на работу программного обеспечения на Facebook и Microsoft. Я также не удалось нескольким кодированным интервью, когда я не был готов.)

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

  • Есть ли кандидат способность строить программы исполнителя
  • Есть ли кандидат способность эффективно использовать ресурсы
  • Независимо от того, есть ли кандидатский опыт и техническую глубину

Если вы ищете полный курс по параллелизму для интервью, C.h.h Afzal , ветеран силиконовой долины и эксперта по совпадениям, создал курсы в Python , Java , C # и Ruby Отказ

Интервью совпадения необходимы, если вы хотите добиться успеха в качестве инженера-программного обеспечения, но множество инженеров болит вопросы собеседования параллелизма (включая себя, когда я проснулся!). Есть несколько основных причин этого:

  • Параллельность – очень сложная тема, где многие младшие разработчики и даже старшие разработчики не имели возможности внедрить параллельные программы.
  • Количество абстракций может быть запутано. Выбор правильной абстракции сложно.
  • Важные уроки инкапсуляции, разделение опасений, свободных сцеплений и т. Д. Все применяются.
  • Большинство из того, что было преподано в вводных многопотативных материалах, технически правильно, но не переводится на проблемы под рукой.

Хорошая новость в том, что в Обучающиеся Мы поговорили с сотнями кандидатов и объединились с C.h. Афзал, кто интервью у некоторых из лучших технологических компаний в мире, включая: Microsoft, Netflix, Cloudera и Oracle, для решения некоторых из наиболее распространенных проблем собеседования.

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

Нить

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

Критический раздел

Критический раздел – это любой кусок кода, который имеет возможность одновременно выполняться более чем одним потоком приложения и обнаруживает любые общие данные или ресурсы, используемые приложением для доступа.

Вы можете подумать о критическом разделе в качестве моста, который может обрабатывать одну машину (I.e. Thread) за раз

Mutex.

Mutex, поскольку подсказки имени подразумевают взаимное исключение. Mutex используется для охраны общих данных, таких как связанный список, массив или любой примитивный тип. Mutex позволяет получить только одну нить для доступа к ресурсу или критическому разделу.

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

Пример на этой иллюстрации представляет Mutex в качестве хранилищной комнаты, указывая на одного клиента (I.E. Thread) за раз

Семафор

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

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

Пример вот очередь за пределами Apple Store Taking, только 50 клиентов могут быть в магазине одновременно

Минимизируйте обмен данными о смежных данных

Вы должны минимизировать обмен данными о смежных данных по двум причинам: производительность (думаю, закон Amdahl) и безопасность. Безопасность в основном о расходах данных. Данная гонка – это ситуация, в которой, по меньшей мере, два потока доступа к общей переменной одновременно. Внутри этого, по крайней мере, один нить пытается изменить переменную.

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

Минимизировать ожидание

Ожидание имеет как минимум два недостатка. Во-первых, когда нить ждет, она не может иметь никакого прогресса; Поэтому ваша производительность идет вниз. Еще хуже: если ожидание занято, базовый ЦП будет полностью использован.

Предпочитаете неизменные данные

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

Осторожно для тупиков (и живых материалов)

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

Теперь я пойду через некоторые из лучших вопросов, которые я рекомендую практиковать.

Чтобы увидеть подробные решения этих проблем, вы можете проверить наши курсы параллелизма в Питон , Java , C # и Ruby Отказ

Постановка задачи

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

Советы, которые помогут решить проблему:

  1. Определите APIS, ваш класс будет разоблачать. В этом случае вам понадобится два для писателя и два для читателя. Эти:

    • AcquireReadlock.
    • releasereadlock.
    • Acquirewritelock.
    • releashritelock.
  2. Подумайте о каждом случае, если вам нужно удовлетворить. Это: до того, как мы позвольте читателю ввести критический раздел, нам нужно убедиться, что писатель не вступает в прогресс. Это нормально, чтобы другие читатели в критическом разделе, поскольку они не делают никаких модификаций. Прежде чем мы позволим писателю ввести критический раздел, нам нужно убедиться, что в критическом разделе нет читателя или писателя.

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

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

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

Общие подводные камни

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

Еще одной распространенной ловушкой проблемы загрузки ReadWrite является голодным. Если писатель поступает, пока есть читатели в критическом разделе, он может подождать в очереди навсегда, когда читатели приходят и уходят. Пока новый читатель прибывает до того, как последние из текущих читателей отправляются, в комнате всегда будет хотя бы один читатель. Чтобы помочь избежать этого, вы можете добавить Mutex для читателей и разрешить писателям блокировать его.

Постановка задачи

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

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

Советы, которые помогут решить проблему

  1. Подумайте о круговом состоянии ожидания и как предотвратить его

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

  3. Когда философ хочет поесть, ему нужна вилка слева и справа от него. Так:

    • Философ A (0) нуждается в вилках 4 и 0
    • Философ B (1) нуждается в вилках 0 и 1
    • Философ C (2) нуждается в вилках 1 и 2
    • Философ D (3) нуждается в вилках 2 и 3
    • Философ E (4) нуждается в вилках 3 и 4
  4. Каждый поток (философер) должен будет рассказать вам, какой ID он должен попытаться заблокировать соответствующие вилки.

Общие подводные камни

Распространенная поднапряжение, которые зарабатывают здесь разработчики, – это круговое ожидание, которое является одним из четырех условий Coffhan. Круговое ожидание описывает условие, когда два или более процессов ждут ресурсов, удерживаемых одним из других процессов. Чтобы избежать этой ловушки, вы должны навязывать упорядочение в переменных условиях (то есть номер вилки 0-4) и сообщите каждому из философов, чтобы подобрать нижнюю численность вилкой.

Увеличение – это также еще одна распространенная ловушка. Представьте, что вы пытаетесь голодать философ 0. Первоначально 2 и 4 находятся за столом, а 1 и 3 голодны. Представьте, что 2 встают и 1 садится; Тогда 4 встает и 3 садится. Теперь вы находитесь в зеркальном образе исходной позиции. Если 3 встает и 4 садится, а затем 1 встает и 2 садится, мы вернулись, где мы начали. Мы могли бы повторить цикл бесконечно и философ 0 будет голодать.

Постановка задачи

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

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

Советы, которые помогут решить проблему

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

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

    • Вы можете создавать две переменные для этой цели и изменять их в блокировке/Mutex. В этой проблеме вы можете использовать объект класса Mutex при манипулировании счетчиков для демократов и республиканцев.
  3. Если ваш первый поток является демократом, который вызывает SeadDemocrat () И нет никаких других доступных гонщиков, его следует поставить, чтобы дождаться, которое вы можете сделать с семафором. Вы должны воздерживаться от использования барьера, потому что неясно, какая будущая партия (то есть демократ или республиканский).

  4. Используйте два разных семафорах ДемократСумирование и Республиканцыwaiting Отказ Это обеспечит вашу первую поток демократов замок () Переменная Mutex Lock, обнаружила, что никакие другие гонщики не существуют, отпустите объект блокировки и продолжайте ждать на ДемократСумирование семафор.

  5. Подумайте об использовании случаи демократную поток должен проверить:

    • Если уже есть 3 ожидания демократов, то мы сигнализируем на ДемократСумирование Семафор три раза, чтобы все эти четыре демократа могли ездить вместе в следующей езде Uber.
    • Если есть две или более республиканские потоки, ожидающие и по крайней мере два демократных потока (включая текущий поток), то текущий демократ-тема может сигнализировать Республиканцыwaiting семафор дважды, чтобы выпустить два ожидающих республиканских потоках и сигнализируют о ДемократСумирование Семафор один раз, чтобы выпустить еще одну тему демократ. Вместе четверо из них составляют следующую поездку, состоящую из двух республиканцев и двух демократов.
    • Если вышеупомянутые два состояния не соответствуют действительности, то нынешняя демократная тема должна просто ждать себя в ДемократСумирование Семафор и выпустите Mutex, чтобы теперь другие нити могли ввести критические разделы.
  6. Ключ должен понять, что каждый поток входит в критические разделы SeadDemocrat () или Seatrepublican () по одному из-за замка в начале двух методов. Независимо от того, равноведно ли езда между двумя типами гонщиков или полностью состоит из одного типа гонщиков зависит от порядка, в котором темы входят в критический раздел.

Общие подводные камни

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

Постановка задачи

Представьте, что у нас есть AsynceEcecutor класс, который выполняет некоторую полезную задачу асинхронно через метод Выполнить () Отказ Кроме того, метод принимает функциональный объект, который действует как обратный вызов, и вызывается после выполнения асинхронного выполнения. Асинхронная работа смоделирована с использованием Спать Отказ Пропущенное вызов вызывается, чтобы позволить INCOOKE принять любые желаемое действие после завершения асинхронной обработки.

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

Советы, которые помогут решить проблему

  1. Требование, чтобы основной нить должен заблокировать до тех пор, пока асинхронное исполнение не является полным подсказками при использовании некоторого механизма уведомления/сигнализации.

    • На первый взгляд, вы можете использовать семафор, но вместо этого вы можете использовать переменную условия и пару Mutex для достижения одной и той же функциональности
  2. Поскольку вы не можете изменить оригинальный код, вы можете продлить новый класс Synchronousexecutor от данного AsynceEcecutor класс и переопределить Выполнить () метод. Хитрость здесь состоит в том, чтобы вызвать оригинальную асинхронную реализацию, используя Super () внутри переопределенного метода.

Общие подводные камни

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

Постановка задачи

Парикмахерская состоит из комнаты ожидания с n стульями и креслом парикмахера для дающих стрижки. Если клиентов не будут поданы, парикмахерская идет спать. Если клиент входит в парикмахерскую, и все стулья заняты, тогда клиент покидает магазин. Если парикмахерская занята, но стулья доступны, затем клиент сидит в одном из бесплатных стульев. Если парикмахер спит, клиент просыпается в парикмахерской. Напишите программу для координации взаимодействия между парикмахером и клиентами.

Советы, которые помогут решить проблему

  1. Сначала определите различные государственные переходы для этой проблемы. Давайте посмотрим на них по частям:
    • Заказчик входит в магазин, и если все N стулья заняты, он уходит. Это намеки на поддержание подсчета клиентов ожидания.
    • Если какой-либо из n стульев свободен, клиент берет на себя стул, чтобы дождаться его очереди. Обратите внимание, что это переводит на использование семафорна, на котором темы, которые нашли бесплатный стул, дождитесь, прежде чем быть вызванным парикмахером для стрижки.
    • Если клиент входит в магазин, и парикмахерс заснут, он подразумевает, что в магазине нет клиентов. Только введенный поток клиентов просыпается в резьбе парикмахерской. Это звучит так, как использовать сигнальную конструкцию, чтобы разбудить резьбу парикмахерской.

Общие подводные камни

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

  • Барбер никто не сидит в кресле и думает, что зал ожидания пусто, так идет спать
  • Клиент считает, что парикмахер занят, поэтому не пытается просыпаться парикмахера и просто терпеливо ждет парикмахера

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

Единственный способ стать лучше по проблемам параллелизма – это практиковать их.

Если вы ищете подробные ответы на вышеуказанные вопросы, наряду с другими лучшими вопросами собеседования совпадения, включая проблему в ванной комнате унисекс и безрезультатно Singleton, я настоятельно рекомендую взглянуть на наши курсы собеседования в Python , Java , Ruby и C # Отказ

Счастливое интервью!

Дополнительное чтение:

Оригинал: “https://dev.to/educative/top-5-concurrency-interview-questions-for-software-engineers-1ng0”