Найти в Дзене

Чистый код. Конспект. Глава 13. Часть 2. Многопоточность.

Сегодня будет сложно. Заметки: Существуют несколько различных вариантов, как программа может себя вести. Но сначала немного определений: А теперь немного про модели в многопоточной среде: Большинство проблем в многопоточности — одна из трех моделей. Советы:

Сегодня будет сложно. Заметки:

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

  1. Связанные ресурсы — ресурсы с фиксированным размером или количеством, которые существуют в многопоточной среде.
  2. Взаимное исключение — в любой момент, если существуют общие данные или ресурсы, то может работать только один поток.
  3. Зависание — Работа потока/ов приостанавливается на слишком долгое время. Например, если мы всегда разрешаем высокоприоритетным потокам работать первыми, то существует шанс, что низкоприоритетные потоки будут в вечном ожидании.
  4. Взаимная блокировка — потоки бесконечно ожидают завершения друг друга. Каждый поток захватил ресурс, который необходим для работы другому потоке.
  5. Обратная блокировка — потоки не могут разойтись. Каждый пытается делать свою работу, но ему мешают.

А теперь немного про модели в многопоточной среде:

  1. Производители-потребители (активная блокировка) — Производители создают задания и кладут их в очередь. Потребители извлекают из очереди и выполняют. Обе стороны ждут оповещения, чтобы начать работу (поместить в очередь, если есть место, или взять в работу, если появилось что-то).
  2. Читатели-писатели — когда есть общий ресурс, который читают, но его надо периодически обновлять. Очень важно найти баланс, чтобы был хороший режим работы и нормальная производительность и не было устаревших данных.
  3. Обедающие философы —конкуренция за ресурсы. Почему так
    называется? Есть философы за круглым столом — в центре тарелка со спагетти — когда проголодался — надо взять две вилки (справа и слева — получается, что каждая вилка на двоих человек), но если одна вилка уже занята — приходится ждать. Конкуренция может привести к возникновению взаимных блокировок, обратимых блокировок, падению производительности и эффективности работы.

Большинство проблем в многопоточности — одна из трех моделей.

Советы:

  1. Избегайтесь зависимостей между синхронизированными методами. Есть стандартные решения: блокировка на стороне клиента (при вызове первого метода до последнего). Вот тут не очень понятно, что имел в виду автор. Надо будет подробнее почитать потом.
  2. Блокировка на стороне сервера — он создает метод, который блокирует сервер. После вызова всех методов блокировка снимается.
  3. Адаптирующий сервер — создается посредник с блокировкой.
  4. Синхронизированные секции должны быть минимальными.Блокировки обходятся дорого, потому что создают задержки и увеличивают затраты ресурсов.
  5. Одна из типичных проблем — взаимная блокировка программных потоков, бесконечно долго ожидающих сигнала на продолжение работы. Например, если родитель создаст потомков и будет ждать их завершения, то если один из дочерних попадет в дедлок, то система не сможет корректно завершиться. Аналогично с производитель-потребитель. Родитель дает сигнал — производитель получает сигнал и прерывает работу. Потребитель ждет сообщение от производителя и блокируется в состояние, когда не может получить сигнал завершения.
  6. Начинайте думать о корректном завершении на ранней стадии разработки.
  7. Пишите много тестов на все случаи жизни (разные платформы, количество потоков больше процессоров, создавайте ситуации для повышения вероятности сбоя). Чем чаще происходит переключение задач, тем больше вероятность выявления пропущенной критической секции или возникновения взаимной блокировки.
  8. Не игнорируйте системные ошибки. Даже если у вас приложение упало всего один раз из тысячи.
  9. Не пытайтесь одновременно отлавливать ошибки в обычном и многопоточном коде. Но начните отладку с обычного, чтобы убедиться, что все ок там.
  10. Реализуйте код так, чтобы он мог выполняться в различных конфигурациях.
  11. Найдите средства измерения производительности системы в различных конфигурациях. Рассмотрите возможность автоматической настройки в зависимости от текущей производительности и загрузки системы.
  12. Можно тестить добавив sleep, wait, yield, priority. Каждый из методов меняет порядок выполнения программы. Если что-то упало, то это виноват не вставленный метод, а ваш код.
  13. Есть некие программы в стиле ConTest для тестов многопоточного кода. Я не нашла её, но автор использует именно такое название.
  14. Используйте стратегию случайного выбора пути выполнения для выявления ошибок. Т.е. рандомно вставляйте методы из 12 пункта.
  15. Следуйте принципу единственной ответственности и разбейте систему на POJO-объекты, отделяющие многопоточный код от кода, не связанного с потоками.