![]() Главная страница Случайная страница КАТЕГОРИИ: АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника |
Занятие 11. Взаимодействие потоков
План занятия: · Основные принципы взаимодействия потоков · Основные проблемы взаимодействия потоков. Проблема соревнований · Критические секции · Блокирование
Основные принципы взаимодействия потоков Потоки, которые выполняются в рамках процесса параллельно, могут быть независимыми или взаимодействовать между собой. Поток является независимым, если он не влияет на выполнение других потоков процесса, не подвергается воздействию с их стороны, и не имеет с ними никаких общих данных. Его исполнение однозначно зависит от входных данных и он называется детерминированным. Все остальные потоки взаимодействуют друг с другом. Эти потоки имеют данные, общие с другими потоками (они находятся в адресном пространстве их процесса). Их выполнение зависит не только от входных данных, но и от выполнения других потоков, то есть они являются недетерминированными. Результаты выполнения независимого потока всегда можно повторить, чего нельзя сказать о потоках, взаимодействующих. Данные, которые являются общими для нескольких потоков, называют совместно используемыми данными (shared data). Это - важнейшая концепция программирования. Всякий поток может в любой момент времени изменить такие данные. Механизмы обеспечения корректного доступа к совместно используемым данным называют механизмами синхронизации потоков. Работать с независимыми потоками проще, чем с теми, которые взаимодействуют. Программист может не учитывать того, что одновременно с таким потоком выполняются другие, а также не обращать внимания на состояние совместно используемых данных, с которыми работает поток. Однако обойтись без реализации взаимодействия потоков невозможно по нескольким причинам:
Необходимость организации параллельного выполнения взаимодействующих потоков, требует наличия механизмов обмена данными между ними и обеспечение их синхронизации. Основные проблемы взаимодействия потоков. Проблема соревнований В связи с тем, что все потоки в системе выполняются последовательно, это приводит к следующему: в одной ситуации код может работать, в другой - нет, и предсказать появление ошибки в общем случае невозможно. Такую ситуацию называют состоянием гонок или соревнованием (Rасе condition), что является одной из наиболее трудно улавливаемых ошибок, с которыми сталкиваются программисты. Она практически не поддается традиционному налаживанию (поскольку невозможно взять в отладчик все возможные комбинации последовательностей выполнения потоков, особенно если их много). Попытки решать подобные проблемы вызвали необходимость синхронизации потоков. Сразу же отметим, что проблемы синхронизации и организации параллельных вычислений являются одними из самых сложных в практическом программировании. Поэтому разработку и особенно налаживания многопоточных программ часто воспринимают как своеобразное «искусство», что доступно далеко не всем программистам. На самом деле такая разработка и отладка - это отнюдь не искусство, а строгая дисциплина, подлежит одному главному принципу: поскольку для многопоточных программ традиционное налаживания не пригодно, программист должен писать код таким образом, чтобы уже на этапе разработки не оставить места для ошибок синхронизации. В этом разделе ознакомимся с правилами, которые необходимо соблюдать, чтобы созданный код соответствовал этому принципу. Рассмотрим основные подходы к решению проблемы соревнований:
Критические секции Рассмотрим использование простейшей идеи для решения проблемы соревнований. Нетрудно заметить, как источником нашей ошибки является то, что внешне простая операция возложение денег на счет в действительности распадается на несколько операций, при этом всегда остается шанс вмешательства между ними какого-то другого потока. В этом случае говорят, что исходная операция не является атомарной. Для решения проблемы соревнования используется превращение фрагмента кода, который вызывает проблему, в атомарную операцию, то есть в такую, которая гарантированно будет выполняться полностью без вмешательства других потоков. Такой фрагмент кода называют критической секцией (critical section) Рассмотрим свойства, которыми должна обладать критическая секция:
Остается ответить на далеко не простой вопрос: «Как нам заставить систему воспринимать несколько операций как одну единую операцию?» Самым простым решением такой задачи было бы запретить прерывание на время исполнения кода критической секции. Такой подход, хотя и решает задачи в принципе, на практике не может быть применяемый, поскольку вследствие зацикливания или аварии программы в критической секции вся система может остаться с заблокированными прерываниями, а следовательно, в неработоспособном состоянии. Блокирование Рациональным решением является использование блокировок (locks). Блокировка - это механизм, который не позволяет более чем одному потоку выполнять код критической секции. Использование блокировки сводится к двум действиям: введение и снятие блокировки. В случае блокирования проверяют, не было ли оно уже сделано другим потоком, и если это так, этот поток переходит в состояние ожидания, иначе он вводит блокировки и входит в критическую секцию. После выхода из критической секции поток снимает блокировку. Так реализуют свойство взаимного исключения, отсюда происходит другое название для блокировки - мьютекс (mutex, сокращение от mutual exclusion). Впрочем, чаще это название обозначает конкретный механизм ОС, реализующей блокировки.
|