Многопоточность

Поделись знанием:
Перейти к: навигация, поиск

Многопото́чность — свойство платформы (например, операционной системы, виртуальной машины и т. д.) или приложения, состоящее в том, что процесс, порождённый в операционной системе, может состоять из нескольких потоков, выполняющихся «параллельно», то есть без предписанного порядка во времени. При выполнении некоторых задач такое разделение может достичь более эффективного использования ресурсов вычислительной машины.

Такие потоки называют также потоками выполнения (от англ. thread of execution); иногда называют «нитями» (буквальный перевод англ. thread) или неформально «тредами».





Описание

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

Многопоточность (как доктрину программирования) не следует путать ни с многозадачностью, ни с многопроцессорностью, несмотря на то, что операционные системы, реализующие многозадачность, как правило, реализуют и многопоточность.

К достоинствам многопоточности в программировании можно отнести следующее:

  • Упрощение программы в некоторых случаях за счет использования общего адресного пространства.
  • Меньшие относительно процесса временны́е затраты на создание потока.
  • Повышение производительности процесса за счет распараллеливания процессорных вычислений и операций ввода-вывода.

Аппаратная реализация

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

Различают две формы многопоточности, которые могут быть реализованы в процессорах аппаратно:

Типы реализации потоков

  • Поток в пространстве пользователя. Каждый процесс имеет таблицу потоков, аналогичную таблице процессов ядра. К недостаткам можно отнести:
  1. Отсутствие прерывания по таймеру внутри одного процесса
  2. При использовании блокирующего системного запроса для процесса все его потоки блокируются.
  3. Сложность реализации
  • Поток в пространстве ядра. Наряду с таблицей процессов в пространстве ядра имеется таблица потоков.
  • «Волокна» (англ. fibers). Несколько потоков режима пользователя, исполняющихся в одном потоке режима ядра. Поток пространства ядра потребляет заметные ресурсы, в первую очередь физическую память и диапазон адресов режима ядра для стека режима ядра. Поэтому было введено понятие «волокна» — облегчённого потока, выполняемого исключительно в режиме пользователя. У каждого потока может быть несколько «волокон».

Взаимодействие потоков

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

  • Взаимоисключения (mutex, мьютекс) — это объект синхронизации, который устанавливается в особое сигнальное состояние, когда не занят каким-либо потоком. Только один поток владеет этим объектом в любой момент времени, отсюда и название таких объектов (от английского mutually exclusive access — взаимно исключающий доступ) — одновременный доступ к общему ресурсу исключается. После всех необходимых действий мьютекс освобождается, предоставляя другим потокам доступ к общему ресурсу. Объект может поддерживать рекурсивный захват второй раз тем же потоком, увеличивая счетчик, не блокируя поток, и требуя потом многократного освобождения. Такова, например, критическая секция в Win32. Тем не менее, есть и такие реализации, которые не поддерживают такое и приводят к взаимной блокировке потока при попытке рекурсивного захвата. Это FAST_MUTEX в ядре Windows.
  • Семафоры представляют собой доступные ресурсы, которые могут быть приобретены несколькими потоками в одно и то же время, пока пул ресурсов не опустеет. Тогда дополнительные потоки должны ждать, пока требуемое количество ресурсов не будет снова доступно. Семафоры очень эффективны, поскольку они позволяют одновременный доступ к ресурсам.
  • События. Объект, хранящий в себе 1 бит информации «просигнализирован или нет», над которым определены операции «просигнализировать», «сбросить в непросигнализированное состояние» и «ожидать». Ожидание на просигнализированном событии есть отсутствие операции с немедленным продолжением исполнения потока. Ожидание на непросигнализированном событии приводит к приостановке исполнения потока до тех пор, пока другой поток (или же вторая фаза обработчика прерывания в ядре ОС) не просигнализирует событие. Возможно ожидание нескольких событий в режимах «любого» или «всех». Возможно также создание события, автоматически сбрасываемого в непросигнализированное состояние после пробуждения первого же — и единственного — ожидающего потока (такой объект используется как основа для реализации объекта «критическая секция»). Активно используются в MS Windows, как в режиме пользователя, так и в режиме ядра. Аналогичный объект имеется и в ядре Linux под названием kwait_queue.
  • Критические секции обеспечивают синхронизацию подобно мьютексам, за исключением того, что объекты, представляющие критические секции, доступны в пределах одного процесса. События, мьютексы и семафоры также можно использовать в однопроцессном приложении, однако реализации критических секций в некоторых ОС (например, Windows NT) обеспечивают более быстрый и более эффективный[1][2] механизм взаимно-исключающей синхронизации — операции «получить» и «освободить» на критической секции оптимизированы для случая единственного потока (отсутствия конкуренции) с целью избежать любых ведущих в ядро ОС системных вызовов. Подобно мьютексам объект, представляющий критическую секцию, может использоваться только одним потоком в данный момент времени, что делает их крайне полезными при разграничении доступа к общим ресурсам.
  • Условные переменные (condvars). Сходны с событиями, но не являются объектами, занимающими память — используется только адрес переменной, понятие «содержимое переменной» не существует, в качестве условной переменной может использоваться адрес произвольного объекта. В отличие от событий, установка условной переменной в просигнализированное состояние не влечет за собой никаких последствий в случае, если на данный момент нет потоков, ожидающих на переменной. Установка события в аналогичном случае влечет за собой запоминание состояния «просигнализировано» внутри самого события, после чего следующие потоки, желающие ожидать события, продолжают исполнение немедленно без остановки. Для полноценного использования такого объекта необходима также операция «освободить mutex и ожидать условную переменную атомарно». Активно используются в UNIX-подобных ОС. Дискуссии о преимуществах и недостатках событий и условных переменных являются заметной частью дискуссий о преимуществах и недостатках Windows и UNIX.
  • Порт завершения ввода-вывода (IO completion port, IOCP). Реализованный в ядре ОС и доступный через системные вызовы объект «очередь» с операциями «поместить структуру в хвост очереди» и «взять следующую структуру с головы очереди» — последний вызов приостанавливает исполнение потока в случае, если очередь пуста, и до тех пор, пока другой поток не осуществит вызов «поместить». Самой важной особенностью IOCP является то, что структуры в него могут помещаться не только явным системным вызовом из режима пользователя, но и неявно внутри ядра ОС как результат завершения асинхронной операции ввода-вывода на одном из дескрипторов файлов. Для достижения такого эффекта необходимо использовать системный вызов «связать дескриптор файла с IOCP». В этом случае помещенная в очередь структура содержит в себе код ошибки операции ввода-вывода, а также, для случая успеха этой операции — число реально введенных или выведенных байт. Реализация порта завершения также ограничивает число потоков, исполняющихся на одном процессоре/ядре после получения структуры из очереди. Объект специфичен для MS Windows, и позволяет обработку входящих запросов соединения и порций данных в серверном программном обеспечении в архитектуре, где число потоков может быть меньше числа клиентов (нет требования создавать отдельный поток с расходами ресурсов на него для каждого нового клиента).
  • ERESOURCE. Мьютекс, поддерживающий рекурсивный захват, с семантикой разделяемого или эксклюзивного захвата. Семантика: объект может быть либо свободен, либо захвачен произвольным числом потоков разделяемым образом, либо захвачен всего одним потоком эксклюзивным образом. Любые попытки осуществить захваты, нарушающее это правило, приводят к блокировке потока до тех пор, пока объект не освободится так, чтобы сделать захват разрешенным. Также есть операции вида TryToAcquire — никогда не блокирует поток, либо захватывает, либо (если нужна блокировка) возвращает FALSE, ничего не делая. Используется в ядре Windows, особенно в файловых системах — так, например, любому кем-то открытому дисковому файлу соответствует структура FCB, в которой есть 2 таких объекта для синхронизации доступа к размеру файла. Один из них — paging IO resource — захватывается эксклюзивно только в пути обрезания файла, и гарантирует, что в момент обрезания на файле нет активного ввода-вывода от кэша и от отображения в память.
  • Rundown protection. Полудокументированный (вызовы присутствуют в файлах-заголовках, но отсутствуют в документации) объект в ядре Windows. Счетчик с операциями «увеличить», «уменьшить» и «ждать». Ожидание блокирует поток до тех пор, пока операции уменьшения не уменьшат счетчик до нуля. Кроме того, операция увеличения может отказать, и наличие активного в данный момент времени ожидания заставляет отказывать все операции увеличения.

Критика терминологии

Перевод английского термина thread как «поток» в контексте, связанном с программированием, противоречит его же переводу «нить» в общеязыковом контексте, а также создает коллизии с термином Data stream.

Однако термин «поток» связан с переводами иностранной технической литературы, выполненными в 1970-х годах издательством «Мир». В настоящее время в «академических кругах» (то есть в учебниках, методических пособиях, курсах вузов, диссертациях и пр.) он считается эталонным. Термины же «нить», «тред» и т. п. считаются техническими жаргонизмами.

См. также

Напишите отзыв о статье "Многопоточность"

Примечания

  1. Richter. "Джеффри Рихтер. Windows для профессионалов. Создание эффективных WIN32-приложений с учетом специфики 64-разрядной версии Windows. 2001 год
  2. MSDN msdn.microsoft.com/en-us/library/ms682530%28VS.85%29.aspx

Ссылки

  • [software.intel.com/ru-ru/articles/writing-parallel-programs-a-multi-language-tutorial-introduction/ Введение в технологии параллельного программирования]  (рус.)
  • hardclub.donntu.edu.ua/projects/qt/qq/qq11-mutex.html#understandingmutexesandsemaphores
  • [www.codenet.ru/progr/cpp/threads.php Введение в многопоточность]

Отрывок, характеризующий Многопоточность

– Мой милый, – отвечал Анатоль по французски (как и шел весь разговор), я не считаю себя обязанным отвечать на допросы, делаемые в таком тоне.
Лицо Пьера, и прежде бледное, исказилось бешенством. Он схватил своей большой рукой Анатоля за воротник мундира и стал трясти из стороны в сторону до тех пор, пока лицо Анатоля не приняло достаточное выражение испуга.
– Когда я говорю, что мне надо говорить с вами… – повторял Пьер.
– Ну что, это глупо. А? – сказал Анатоль, ощупывая оторванную с сукном пуговицу воротника.
– Вы негодяй и мерзавец, и не знаю, что меня воздерживает от удовольствия разможжить вам голову вот этим, – говорил Пьер, – выражаясь так искусственно потому, что он говорил по французски. Он взял в руку тяжелое пресспапье и угрожающе поднял и тотчас же торопливо положил его на место.
– Обещали вы ей жениться?
– Я, я, я не думал; впрочем я никогда не обещался, потому что…
Пьер перебил его. – Есть у вас письма ее? Есть у вас письма? – повторял Пьер, подвигаясь к Анатолю.
Анатоль взглянул на него и тотчас же, засунув руку в карман, достал бумажник.
Пьер взял подаваемое ему письмо и оттолкнув стоявший на дороге стол повалился на диван.
– Je ne serai pas violent, ne craignez rien, [Не бойтесь, я насилия не употреблю,] – сказал Пьер, отвечая на испуганный жест Анатоля. – Письма – раз, – сказал Пьер, как будто повторяя урок для самого себя. – Второе, – после минутного молчания продолжал он, опять вставая и начиная ходить, – вы завтра должны уехать из Москвы.
– Но как же я могу…
– Третье, – не слушая его, продолжал Пьер, – вы никогда ни слова не должны говорить о том, что было между вами и графиней. Этого, я знаю, я не могу запретить вам, но ежели в вас есть искра совести… – Пьер несколько раз молча прошел по комнате. Анатоль сидел у стола и нахмурившись кусал себе губы.
– Вы не можете не понять наконец, что кроме вашего удовольствия есть счастье, спокойствие других людей, что вы губите целую жизнь из того, что вам хочется веселиться. Забавляйтесь с женщинами подобными моей супруге – с этими вы в своем праве, они знают, чего вы хотите от них. Они вооружены против вас тем же опытом разврата; но обещать девушке жениться на ней… обмануть, украсть… Как вы не понимаете, что это так же подло, как прибить старика или ребенка!…
Пьер замолчал и взглянул на Анатоля уже не гневным, но вопросительным взглядом.
– Этого я не знаю. А? – сказал Анатоль, ободряясь по мере того, как Пьер преодолевал свой гнев. – Этого я не знаю и знать не хочу, – сказал он, не глядя на Пьера и с легким дрожанием нижней челюсти, – но вы сказали мне такие слова: подло и тому подобное, которые я comme un homme d'honneur [как честный человек] никому не позволю.
Пьер с удивлением посмотрел на него, не в силах понять, чего ему было нужно.
– Хотя это и было с глазу на глаз, – продолжал Анатоль, – но я не могу…
– Что ж, вам нужно удовлетворение? – насмешливо сказал Пьер.
– По крайней мере вы можете взять назад свои слова. А? Ежели вы хотите, чтоб я исполнил ваши желанья. А?
– Беру, беру назад, – проговорил Пьер и прошу вас извинить меня. Пьер взглянул невольно на оторванную пуговицу. – И денег, ежели вам нужно на дорогу. – Анатоль улыбнулся.
Это выражение робкой и подлой улыбки, знакомой ему по жене, взорвало Пьера.
– О, подлая, бессердечная порода! – проговорил он и вышел из комнаты.
На другой день Анатоль уехал в Петербург.


Пьер поехал к Марье Дмитриевне, чтобы сообщить об исполнении ее желанья – об изгнании Курагина из Москвы. Весь дом был в страхе и волнении. Наташа была очень больна, и, как Марья Дмитриевна под секретом сказала ему, она в ту же ночь, как ей было объявлено, что Анатоль женат, отравилась мышьяком, который она тихонько достала. Проглотив его немного, она так испугалась, что разбудила Соню и объявила ей то, что она сделала. Во время были приняты нужные меры против яда, и теперь она была вне опасности; но всё таки слаба так, что нельзя было думать везти ее в деревню и послано было за графиней. Пьер видел растерянного графа и заплаканную Соню, но не мог видеть Наташи.
Пьер в этот день обедал в клубе и со всех сторон слышал разговоры о попытке похищения Ростовой и с упорством опровергал эти разговоры, уверяя всех, что больше ничего не было, как только то, что его шурин сделал предложение Ростовой и получил отказ. Пьеру казалось, что на его обязанности лежит скрыть всё дело и восстановить репутацию Ростовой.
Он со страхом ожидал возвращения князя Андрея и каждый день заезжал наведываться о нем к старому князю.
Князь Николай Андреич знал через m lle Bourienne все слухи, ходившие по городу, и прочел ту записку к княжне Марье, в которой Наташа отказывала своему жениху. Он казался веселее обыкновенного и с большим нетерпением ожидал сына.
Чрез несколько дней после отъезда Анатоля, Пьер получил записку от князя Андрея, извещавшего его о своем приезде и просившего Пьера заехать к нему.
Князь Андрей, приехав в Москву, в первую же минуту своего приезда получил от отца записку Наташи к княжне Марье, в которой она отказывала жениху (записку эту похитила у княжны Марьи и передала князю m lle Вourienne) и услышал от отца с прибавлениями рассказы о похищении Наташи.
Князь Андрей приехал вечером накануне. Пьер приехал к нему на другое утро. Пьер ожидал найти князя Андрея почти в том же положении, в котором была и Наташа, и потому он был удивлен, когда, войдя в гостиную, услыхал из кабинета громкий голос князя Андрея, оживленно говорившего что то о какой то петербургской интриге. Старый князь и другой чей то голос изредка перебивали его. Княжна Марья вышла навстречу к Пьеру. Она вздохнула, указывая глазами на дверь, где был князь Андрей, видимо желая выразить свое сочувствие к его горю; но Пьер видел по лицу княжны Марьи, что она была рада и тому, что случилось, и тому, как ее брат принял известие об измене невесты.
– Он сказал, что ожидал этого, – сказала она. – Я знаю, что гордость его не позволит ему выразить своего чувства, но всё таки лучше, гораздо лучше он перенес это, чем я ожидала. Видно, так должно было быть…
– Но неужели совершенно всё кончено? – сказал Пьер.
Княжна Марья с удивлением посмотрела на него. Она не понимала даже, как можно было об этом спрашивать. Пьер вошел в кабинет. Князь Андрей, весьма изменившийся, очевидно поздоровевший, но с новой, поперечной морщиной между бровей, в штатском платье, стоял против отца и князя Мещерского и горячо спорил, делая энергические жесты. Речь шла о Сперанском, известие о внезапной ссылке и мнимой измене которого только что дошло до Москвы.
– Теперь судят и обвиняют его (Сперанского) все те, которые месяц тому назад восхищались им, – говорил князь Андрей, – и те, которые не в состоянии были понимать его целей. Судить человека в немилости очень легко и взваливать на него все ошибки другого; а я скажу, что ежели что нибудь сделано хорошего в нынешнее царствованье, то всё хорошее сделано им – им одним. – Он остановился, увидав Пьера. Лицо его дрогнуло и тотчас же приняло злое выражение. – И потомство отдаст ему справедливость, – договорил он, и тотчас же обратился к Пьеру.
– Ну ты как? Все толстеешь, – говорил он оживленно, но вновь появившаяся морщина еще глубже вырезалась на его лбу. – Да, я здоров, – отвечал он на вопрос Пьера и усмехнулся. Пьеру ясно было, что усмешка его говорила: «здоров, но здоровье мое никому не нужно». Сказав несколько слов с Пьером об ужасной дороге от границ Польши, о том, как он встретил в Швейцарии людей, знавших Пьера, и о господине Десале, которого он воспитателем для сына привез из за границы, князь Андрей опять с горячностью вмешался в разговор о Сперанском, продолжавшийся между двумя стариками.
– Ежели бы была измена и были бы доказательства его тайных сношений с Наполеоном, то их всенародно объявили бы – с горячностью и поспешностью говорил он. – Я лично не люблю и не любил Сперанского, но я люблю справедливость. – Пьер узнавал теперь в своем друге слишком знакомую ему потребность волноваться и спорить о деле для себя чуждом только для того, чтобы заглушить слишком тяжелые задушевные мысли.
Когда князь Мещерский уехал, князь Андрей взял под руку Пьера и пригласил его в комнату, которая была отведена для него. В комнате была разбита кровать, лежали раскрытые чемоданы и сундуки. Князь Андрей подошел к одному из них и достал шкатулку. Из шкатулки он достал связку в бумаге. Он всё делал молча и очень быстро. Он приподнялся, прокашлялся. Лицо его было нахмурено и губы поджаты.
– Прости меня, ежели я тебя утруждаю… – Пьер понял, что князь Андрей хотел говорить о Наташе, и широкое лицо его выразило сожаление и сочувствие. Это выражение лица Пьера рассердило князя Андрея; он решительно, звонко и неприятно продолжал: – Я получил отказ от графини Ростовой, и до меня дошли слухи об искании ее руки твоим шурином, или тому подобное. Правда ли это?
– И правда и не правда, – начал Пьер; но князь Андрей перебил его.
– Вот ее письма и портрет, – сказал он. Он взял связку со стола и передал Пьеру.
– Отдай это графине… ежели ты увидишь ее.
– Она очень больна, – сказал Пьер.
– Так она здесь еще? – сказал князь Андрей. – А князь Курагин? – спросил он быстро.
– Он давно уехал. Она была при смерти…
– Очень сожалею об ее болезни, – сказал князь Андрей. – Он холодно, зло, неприятно, как его отец, усмехнулся.
– Но господин Курагин, стало быть, не удостоил своей руки графиню Ростову? – сказал князь Андрей. Он фыркнул носом несколько раз.
– Он не мог жениться, потому что он был женат, – сказал Пьер.
Князь Андрей неприятно засмеялся, опять напоминая своего отца.
– А где же он теперь находится, ваш шурин, могу ли я узнать? – сказал он.
– Он уехал в Петер…. впрочем я не знаю, – сказал Пьер.
– Ну да это всё равно, – сказал князь Андрей. – Передай графине Ростовой, что она была и есть совершенно свободна, и что я желаю ей всего лучшего.
Пьер взял в руки связку бумаг. Князь Андрей, как будто вспоминая, не нужно ли ему сказать еще что нибудь или ожидая, не скажет ли чего нибудь Пьер, остановившимся взглядом смотрел на него.
– Послушайте, помните вы наш спор в Петербурге, – сказал Пьер, помните о…
– Помню, – поспешно отвечал князь Андрей, – я говорил, что падшую женщину надо простить, но я не говорил, что я могу простить. Я не могу.
– Разве можно это сравнивать?… – сказал Пьер. Князь Андрей перебил его. Он резко закричал:
– Да, опять просить ее руки, быть великодушным, и тому подобное?… Да, это очень благородно, но я не способен итти sur les brisees de monsieur [итти по стопам этого господина]. – Ежели ты хочешь быть моим другом, не говори со мною никогда про эту… про всё это. Ну, прощай. Так ты передашь…
Пьер вышел и пошел к старому князю и княжне Марье.
Старик казался оживленнее обыкновенного. Княжна Марья была такая же, как и всегда, но из за сочувствия к брату, Пьер видел в ней радость к тому, что свадьба ее брата расстроилась. Глядя на них, Пьер понял, какое презрение и злобу они имели все против Ростовых, понял, что нельзя было при них даже и упоминать имя той, которая могла на кого бы то ни было променять князя Андрея.
За обедом речь зашла о войне, приближение которой уже становилось очевидно. Князь Андрей не умолкая говорил и спорил то с отцом, то с Десалем, швейцарцем воспитателем, и казался оживленнее обыкновенного, тем оживлением, которого нравственную причину так хорошо знал Пьер.