Многопоточное управление кучей - PullRequest
11 голосов
/ 29 января 2010

В C / C ++ я могу выделить память в одном потоке и удалить ее в другом потоке. Тем не менее, когда кто-либо запрашивает память у кучи, распределителю кучи необходимо пройтись по куче, чтобы найти свободную область подходящего размера. Как два потока могут эффективно обращаться к одной и той же куче, не повреждая кучу? (Это делается путем блокировки кучи?)

Ответы [ 6 ]

10 голосов
/ 09 января 2011

В общем, вам не нужно беспокоиться о безопасности потоков вашего распределителя памяти. Все стандартные распределители памяти - то есть те, которые поставляются с MacOS, Windows, Linux и т. Д. - являются поточно-ориентированными. Блокировки являются стандартным способом обеспечения безопасности потоков, хотя можно написать распределитель памяти, который использует только атомарные операции, а не блокировки.

Теперь совершенно другой вопрос, являются ли эти распределители памяти scale ; то есть их производительность не зависит от количества потоков, выполняющих операции с памятью? В большинстве случаев ответ - нет; они либо замедляются, либо могут потреблять намного больше памяти. Первый масштабируемый распределитель в обоих измерениях (скорость и пространство) - Hoard (который я написал); распределитель Mac OS X вдохновлен им - и цитирует это в документации - но Hoard работает быстрее. Есть и другие, в том числе Google tcmalloc.

3 голосов
/ 29 января 2010

Да, «обычная» реализация кучи, поддерживающая многопоточный код, обязательно будет включать в себя некоторую блокировку для обеспечения правильной работы.В довольно экстремальных условиях ( лот активности кучи) это может стать узким местом;более специализированные кучи (обычно обеспечивающие какую-то локальную кучу потоков) доступны, что может помочь в этой ситуации.Я использовал "масштабируемый распределитель" Intel TBB до с хорошим эффектом . tcmalloc и jemalloc являются другими примерами malloc, реализованными с учетом многопоточного масштабирования.

Некоторые сравнения синхронизации между однопоточными и многопоточными mallocs здесь .

2 голосов
/ 29 января 2010

Я нашел эту ссылку.

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

2 голосов
/ 29 января 2010

Это вопрос об операционных системах, поэтому ответ будет зависеть от ОС.

В Windows каждый процесс получает свою собственную кучу. Это означает, что несколько потоков в одном процессе (по умолчанию) совместно используют кучу. Таким образом, ОС должна синхронизировать потоки своих вызовов выделения и освобождения для предотвращения повреждения кучи. Если вам не нравится идея возможного конфликта, вы можете обойти его, используя процедуры Heap * . Вы даже можете перегрузить malloc (в C) и new (в C ++) для их вызова.

1 голос
/ 29 января 2010

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

0 голосов
/ 29 января 2010

Это будет сильно зависеть от вашей платформы / ОС, но я считаю, что это нормально для основных систем. C / C ++ не определяют потоки, поэтому по умолчанию я полагаю, что ответ «куча не защищена», что для доступа к куче у вас должна быть какая-то многопоточная защита.

Однако, по крайней мере, с Linux и GCC, я считаю, что включение -pthread автоматически предоставит вам эту защиту ...

Кроме того, вот еще один связанный вопрос:

C ++ новый оператор безопасности потока в Linux и GCC 4

...