В C/С++ я могу выделить память в одном потоке и удалить ее в другом потоке. Но всякий раз, когда вы запрашиваете память из кучи, распределитель кучи должен перемещать кучу, чтобы найти свободную площадь подходящего размера. Как два потока могут обращаться к одной и той же куче эффективно, не повреждая кучу? (Это делается путем блокировки кучи?)
Многопоточное управление кучей
Ответ 1
В общем, вам не нужно беспокоиться о безопасности потоков вашего распределителя памяти. Все стандартные распределители памяти, то есть те, которые поставляются с MacOS, Windows, Linux и т.д., Являются потокобезопасными. Замки являются стандартным способом обеспечения безопасности потоков, хотя можно написать распределитель памяти, который использует только атомарные операции, а не блокировки.
Теперь совершенно другой вопрос: распределены ли эти распределители памяти шкала; то есть их производительность не зависит от количества потоков, выполняющих операции памяти? В большинстве случаев ответ отрицательный; они либо замедляют, либо могут потреблять намного больше памяти. Первым масштабируемым распределителем в обоих измерениях (скорость и пространство) является Hoard (который я написал); Распределитель Mac OS X вдохновлен им - и цитирует его в документации, - но Hoard работает быстрее. Есть и другие, включая Google tcmalloc.
Ответ 2
Да, "обычная" реализация кучи, поддерживающая многопоточный код, обязательно будет включать некоторую блокировку для обеспечения правильной работы. В довольно экстремальных условиях (много активности кучи) это может стать узким местом; доступны более специализированные кучи (обычно предоставляющие какую-то нить-локальную кучу), которые могут помочь в этой ситуации. Я использовал Intel TBB "масштабируемый распределитель" для хорошего эффекта. tcmalloc и jemalloc - другие примеры mallocs с многопоточным масштабированием.
Сравнение времени сравнения между однопоточными и многопоточными mallocs здесь.
Ответ 3
Это вопрос с операционными системами, поэтому ответ будет зависеть от ОС.
В Windows каждый процесс получает свою собственную кучу. Это означает, что несколько потоков в одном процессе (по умолчанию) разделяют кучу. Таким образом, ОС должна поточно синхронизировать свои вызовы выделения и освобождения, чтобы предотвратить повреждение кучи. Если вам не нравится идея возможного спора, которая может возникнуть, вы можете обойти ее, используя "Кучи" подпрограмм. Вы можете даже перегрузить malloc (в C) и новый (на С++), чтобы вызвать их.
Ответ 4
Я нашел эту ссылку.
В принципе, кучу можно разделить на арены. При запросе памяти каждая арена проверяется поочередно, чтобы проверить, заблокирована ли она. Это означает, что разные потоки могут безопасно обращаться к различным частям кучи. Frees немного сложнее, потому что каждый свободный должен быть освобожден от арены, на которую он был выделен. Я предполагаю, что хорошая реализация будет получать разные потоки по умолчанию на разных аренах, чтобы попытаться свести к минимуму конфликт.
Ответ 5
Да, обычно доступ к куче должен быть заблокирован. Каждый раз, когда у вас есть общий ресурс, этот ресурс должен быть защищен; память - это ресурс.
Ответ 6
Это будет сильно зависеть от вашей платформы/ОС, но я считаю, что это вообще нормально в основных системах. C/С++ не определяют потоки, поэтому по умолчанию я считаю, что ответ "куча не защищена", что у вас должна быть какая-то многопоточная защита для вашего кучного доступа.
Однако, по крайней мере, с linux и gcc, я считаю, что включение -pthread даст вам эту защиту автоматически...
Кроме того, вот еще один связанный с этим вопрос: