Autant que je sache, chaque thread obtient une pile distincte lorsque le thread est créé par le système d'exploitation. Je me demande si chaque fil a un tas distinct lui aussi?
Non. Tous les threads partagent un tas commun.
Chaque le thread a une pile privée , dont il peut rapidement ajouter et supprimer des éléments. Cela rend la mémoire basée sur la pile rapide, mais si vous utilisez trop de mémoire de pile, comme cela se produit dans la récursion infinie, vous obtiendrez un débordement de pile.
Étant donné que tous les threads partagent le même segment, l'accès à l'allocateur/désallocateur doit être synchronisé. Il existe différentes méthodes et bibliothèques pour éviter conflit d'allocateur .
Certaines langues vous permettent de créer des pools de mémoire privés ou des tas individuels, que vous pouvez affecter à un seul thread.
Par défaut, C n'a qu'un seul tas.
Cela dit, certains allocateurs qui sont conscients des threads partitionneront le tas afin que chaque thread ait sa propre zone à allouer. L'idée est que cela devrait améliorer l'échelle du tas.
Un exemple d'un tel tas est Hoard .
Dépend du système d'exploitation. Le runtime c standard sur les fenêtres et les unités utilise un tas partagé entre les threads. Cela signifie verrouiller chaque malloc/free.
Sur Symbian, par exemple, chaque thread est livré avec son propre segment de mémoire, bien que les threads puissent partager des pointeurs vers des données allouées dans n'importe quel segment de mémoire. La conception de Symbian est meilleure à mon avis car elle élimine non seulement le besoin de verrouillage pendant l'allocation/la libération, mais encourage également une spécification propre de la propriété des données entre les threads. Dans ce cas également, lorsqu'un thread meurt, il prend tous les objets qu'il a alloués avec lui - c'est-à-dire qu'il ne peut pas divulguer les objets qu'il a alloués, ce qui est une propriété importante à avoir dans les appareils mobiles avec une mémoire contrainte.
Erlang suit également une conception similaire où un "processus" agit comme une unité de collecte des ordures. Toutes les données sont communiquées entre les processus par copie, à l'exception des blobs binaires qui sont comptés par référence (je pense).
Chaque thread a sa propre pile et pile d'appel.
Chaque thread partage le même tas.
Cela dépend de ce que vous voulez dire exactement quand vous dites "tas".
Tous les threads partagent l'espace d'adressage, les objets alloués en tas sont donc accessibles à partir de tous les threads. Techniquement, les piles sont également partagées dans ce sens, c'est-à-dire que rien ne vous empêche d'accéder à la pile d'autres threads (même si cela n'aurait presque aucun sens de le faire).
D'autre part, il existe des structures de tas utilisées pour allouer de la mémoire. C'est là que se fait toute la comptabilité pour l'allocation de mémoire en tas. Ces structures sont organisées de manière sophistiquée pour minimiser les conflits entre les threads - ainsi certains threads peuvent partager une structure de tas (une arène), et certains peuvent utiliser des arènes distinctes.
Voir le fil suivant pour une excellente explication des détails: Comment fonctionne malloc dans un environnement multithread?
De manière générale, tous les threads utilisent le même espace d'adressage et n'ont donc généralement qu'un seul segment.
Cependant, cela peut être un peu plus compliqué. Vous recherchez peut-être Thread Local Storage (TLS), mais il ne stocke que des valeurs uniques.
Spécifique à Windows: l'espace TLS peut être alloué en utilisant TlsAlloc et libéré en utilisant TlsFree (Présentation ici ). Encore une fois, ce n'est pas un tas, juste des DWORD.
Étrangement, Windows prend en charge plusieurs tas par processus. On peut stocker la poignée du tas dans TLS. Vous auriez alors quelque chose comme un "tas local de threads". Cependant, seul le handle n'est pas connu des autres threads, ils peuvent toujours accéder à sa mémoire à l'aide de pointeurs car il s'agit toujours du même espace d'adressage.
[~ # ~] edit [~ # ~] : Certains allocateurs de mémoire (en particulier jemalloc sur FreeBSD) utilisent TLS pour attribuer "arènes" aux fils. Cela permet d'optimiser l'allocation pour plusieurs cœurs en réduisant les frais de synchronisation.
En règle générale, les threads partagent le tas et d'autres ressources, mais il existe des constructions de type thread qui ne le font pas. Parmi ces constructions filiformes figurent les processus légers d'Erlang et les processus complets UNIX (créés avec un appel à fork()
). Vous pouvez également travailler sur la simultanéité multi-machine, auquel cas vos options de communication inter-thread sont considérablement plus limitées.
Sur le système d'exploitation FreeRTOS, les tâches (threads) partagent le même tas mais chacune a sa propre pile. Cela est très pratique lorsqu'il s'agit d'architectures à faible puissance RAM, car le même pool de mémoire peut être accédé/partagé par plusieurs threads, mais cela vient avec une petite capture, le développeur doit gardez à l'esprit qu'un mécanisme de synchronisation de malloc et de free est nécessaire, c'est pourquoi il est nécessaire d'utiliser un certain type de synchronisation/verrouillage de processus lors de l'allocation ou de la libération de mémoire sur le tas, par exemple un sémaphore ou un mutex.