У потоков есть четкая куча?


114

Насколько я знаю, каждый поток получает отдельный стек, когда поток создается операционной системой. Интересно, есть ли у каждого потока отдельная куча?


да, windows и linux, библиотека c

3
Ницца. +1 продолжайте отвечать на эти фундаментальные вопросы.

Ответы:


128

Нет. Все потоки используют общую кучу.

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

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

Некоторые языки позволяют создавать частные пулы памяти или отдельные кучи, которые можно назначать одному потоку.


5
Обычно потоки совместно используют ресурсы, такие как память, поэтому любая реализация потока, не связанная с мозгами, будет совместно использовать кучу.
Р. Мартиньо Фернандес

10
Основная причина , каждый поток имеет свой собственный стек так , что поток может сделать что - то (например , вызов функции а) ...
Эдмунд

3
У каждого потока есть отдельный стек, но он не обязательно «частный». Другие потоки обычно имеют к нему доступ.
zch

you will get a stack overflow.Переполнение стека при переполнении стека!
John Strood

2
@crisron Можно настроить отдельную кучу для каждого потока, но если вы сделаете это вместо использования общей кучи по умолчанию, тогда потоку A станет сложно, например, выделить буфер, заполнить его данными, передать его потоку B , и пусть поток B использует данные, а затем освобождает буфер (поскольку поток B не имеет доступа к куче потока A, поток B не может освободить буфер; лучшее, что может сделать поток B, это передать буфер обратно потоку A снова и есть нить A освободить его).
Джереми Фриснер

9

По умолчанию C имеет только одну кучу.

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

Одним из примеров такой кучи является Hoard .


По умолчанию C и C ++ не имеют нескольких потоков. Спецификация C ++ 2003 по крайней мере не допускает использования потоков при проектировании виртуальной машины, поэтому потоки в C ++ определяются реализацией.
Крис Бек

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

1
Обновление: с C ++ 11 потоки больше не определены.
Michael Dorst

5

Зависит от ОС. Стандартная среда выполнения c в Windows и Unices использует общую кучу между потоками. Это означает блокировку каждого malloc / free.

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

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


3

У каждого потока есть свой стек и стек вызовов.

Каждый поток использует одну и ту же кучу.


3

Это зависит от того, что именно вы имеете в виду, говоря «куча».

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

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


1

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


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

2
fork () может использоваться во многих случаях, когда также могут использоваться потоки. Из-за копирования при записи в системах Unix нет значительной разницы в стоимости. Типичный вариант использования - это когда работник автономен (например, веб-сервер) от остальной части службы. Другая возможность - общаться через стандартный ввод / вывод с основным потоком / программой. fork () сильна в Unix, тогда как другие платформы, такие как Windows, предпочитают многопоточность. Основная причина, вероятно, в том, что использование fork () намного проще и безопаснее, и Unix придерживается этой философии простоты. См., Например, веб-сервер apache с его медленным переходом к потокам.
ypnos

1

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

Однако все может быть немного сложнее. Возможно, вы ищете локальное хранилище потоков (TLS), но оно хранит только отдельные значения.

Специфично для Windows: TLS-пространство можно выделить с помощью TlsAlloc и освободить с помощью TlsFree (обзор здесь ). Опять же, это не куча, а просто DWORD.

Как ни странно, Windows поддерживает несколько куч для каждого процесса. Дескриптор кучи можно сохранить в TLS. Тогда у вас будет что-то вроде «локальной кучи потока». Однако другим потокам неизвестен только дескриптор, они по-прежнему могут обращаться к его памяти с помощью указателей, поскольку это все то же адресное пространство.

РЕДАКТИРОВАТЬ : Некоторые распределители памяти (в частности, jemalloc во FreeBSD) используют TLS для назначения «арен» потокам. Это сделано для оптимизации распределения для нескольких ядер за счет уменьшения накладных расходов на синхронизацию.


> «Как ни странно, Windows поддерживает несколько куч на процесс.», Это совсем не странно, можно использовать разные кучи для разных типов распределения, просто добавляет больше гибкости. Конечно, вы всегда можете перейти к VirtualAlloc и создать свою собственную кучу, как захотите.

1

В операционной системе FreeRTOS задачи (потоки) используют одну и ту же кучу, но каждая из них имеет свой собственный стек. Это очень удобно при работе с архитектурами с низким энергопотреблением и низким объемом оперативной памяти, потому что к одному и тому же пулу памяти могут обращаться / совместно использовать несколько потоков, но это имеет небольшую загвоздку, разработчик должен иметь в виду, что механизм синхронизации malloc and free необходим, поэтому необходимо использовать какой-то тип синхронизации / блокировки процесса при выделении или освобождении памяти в куче, например семафор или мьютекс.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.