¿Los hilos tienen un montón distinto?

Hasta donde sé, cada hilo obtiene una stack distinta cuando el hilo es creado por el sistema operativo. Me pregunto si cada hilo tiene un montón distinto a sí mismo también.

No. Todos los hilos comparten un montón común.

Cada hilo tiene una stack privada , de la que puede agregar y eliminar elementos rápidamente. Esto hace que la memoria basada en stack sea rápida, pero si usa demasiada memoria de stack, como ocurre en la recursión infinita, obtendrá un desbordamiento de stack.

Como todos los hilos comparten el mismo montón, el acceso al asignador / desasignador debe estar sincronizado. Hay varios métodos y bibliotecas para evitar la contención del asignador .

Algunos idiomas le permiten crear grupos privados de memoria, o montones individuales, que puede asignar a un único hilo.

Por defecto, C tiene solo un montón único.

Dicho esto, algunos asignadores que son conocedores de subprocesos dividirán el montón para que cada subproceso tenga su propio área para asignar. La idea es que esto debería mejorar la escala del montón.

Un ejemplo de tal montón es Hoard .

Depende del sistema operativo. El tiempo de ejecución estándar en Windows y Unices usa un montón compartido en los subprocesos. Esto significa bloquear cada malloc / free.

En Symbian, por ejemplo, cada subproceso viene con su propio montón, aunque los subprocesos pueden compartir punteros a los datos asignados en cualquier montón. El diseño de Symbian es mejor en mi opinión, ya que no solo elimina la necesidad de locking durante alloc / free, sino que también fomenta la especificación limpia de la propiedad de los datos entre hilos. También en ese caso, cuando un hilo muere, toma todos los objetos asignados junto con él, es decir, no puede filtrar los objetos que ha asignado, que es una propiedad importante para tener en dispositivos móviles con memoria limitada.

Erlang también sigue un diseño similar donde un “proceso” actúa como una unidad de recolección de basura. Todos los datos se comunican entre procesos mediante copia, a excepción de los blobs binarios que se cuentan como referencia (creo).

Cada hilo tiene su propia stack y stack de llamadas.

Cada hilo comparte el mismo montón.

Depende de qué es exactamente lo que quiere decir cuando dice “montón”.

Todos los subprocesos comparten el espacio de direcciones, por lo que los objetos asignados en el montón son accesibles desde todos los subprocesos. Técnicamente, las stacks también se comparten en este sentido, es decir, nada le impide acceder a la stack de otros hilos (aunque casi nunca tendría sentido hacerlo).

Por otro lado, hay estructuras de montón usadas para asignar memoria. Ahí es donde se realiza toda la contabilidad para la asignación de memoria de montón. Estas estructuras están organizadas de forma sofisticada para minimizar la contención entre los subprocesos, por lo que algunos subprocesos pueden compartir una estructura de montón (una arena), y algunos pueden usar arenas distintas.
Consulte el siguiente hilo para obtener una excelente explicación de los detalles: ¿Cómo funciona malloc en un entorno multiproceso?

Normalmente, los subprocesos comparten el montón y otros recursos, sin embargo, hay construcciones similares a subprocesos que no lo hacen. Entre estas construcciones tipo subprocesos se encuentran los procesos livianos de Erlang y los procesos completos de UNIX (creados con una llamada a fork() ). También podría estar trabajando en la concurrencia de máquinas múltiples, en cuyo caso las opciones de comunicación entre hilos son considerablemente más limitadas.

En términos generales, todos los subprocesos utilizan el mismo espacio de direcciones y, por lo tanto, suelen tener solo un montón.

Sin embargo, puede ser un poco más complicado. Es posible que esté buscando Thread Local Storage (TLS), pero solo almacena valores únicos.

Específico para Windows: el espacio TLS puede asignarse usando TlsAlloc y liberarse usando TlsFree (Información general aquí ). Nuevamente, no es un montón, solo DWORDs.

Extrañamente, Windows admite varios Heaps por proceso. Uno puede almacenar el controlador Heap en TLS. Entonces tendrías algo así como un “Header-Heap local”. Sin embargo, los otros subprocesos solo conocen el identificador, aún pueden acceder a su memoria mediante punteros ya que sigue siendo el mismo espacio de direcciones.

EDITAR : algunos asignadores de memoria (específicamente, jemalloc en FreeBSD) usan TLS para asignar “arenas” a los hilos. Esto se hace para optimizar la asignación de múltiples núcleos al reducir la sobrecarga de sincronización.

En el sistema operativo FreeRTOS, las tareas (hilos) comparten el mismo montón, pero cada uno de ellos tiene su propia stack. Esto es muy útil cuando se trata de architectures bajas de RAM de baja potencia, debido a que varios subprocesos pueden acceder / compartir el mismo grupo de memoria, pero esto tiene un pequeño inconveniente, el desarrollador debe tener en cuenta que un mecanismo para sincronizar malloc y libre es necesario, es por eso que es necesario utilizar algún tipo de sincronización de proceso / locking al asignar o liberar memoria en el montón, por ejemplo, un semáforo o un mutex.