Pour 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 thread a un tas distinct de lui-même également?
Pour 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 thread a un tas distinct de lui-même également?
Réponses:
Non. Tous les threads partagent un tas commun.
Chaque 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écursivité infinie, vous obtiendrez un débordement de pile.
Comme tous les threads partagent le même tas, l'accès à l'allocateur / désallocateur doit être synchronisé. Il existe différentes méthodes et bibliothèques pour éviter les conflits d' allocateurs .
Certains langages vous permettent de créer des pools de mémoire privés, ou des tas individuels, que vous pouvez attribuer à un seul thread.
you will get a stack overflow.
Un débordement de pile sur Stack Overflow!
Par défaut, C n'a qu'un seul tas.
Cela dit, certains allocateurs qui sont conscients des threads partitionneront le tas de sorte que chaque thread ait sa propre zone d'allocation. 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 Windows et Unices utilise un tas partagé entre les threads. Cela signifie verrouiller chaque malloc / free.
Sur Symbian, par exemple, chaque thread est livré avec son propre tas, bien que les threads puissent partager des pointeurs vers des données allouées dans n'importe quel tas. La conception de Symbian est meilleure à mon avis car elle élimine non seulement le besoin de verrouillage pendant alloc / free, mais encourage également une spécification claire de la propriété des données entre les threads. Dans ce cas également, lorsqu'un thread meurt, il emporte avec lui tous les objets qu'il a alloués - 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 ramassage 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).
Cela dépend de ce que vous voulez dire exactement lorsque vous dites "tas".
Tous les threads partagent l'espace d'adressage, de sorte que les objets alloués au tas sont 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 jamais de 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 toute la comptabilité pour l'allocation de mémoire de tas est effectuée. 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 d'autres peuvent utiliser des arènes distinctes.
Voir le fil suivant pour une excellente explication des détails: Comment malloc fonctionne-t-il dans un environnement multithread?
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 de type thread, on trouve les processus légers d'Erlang et les processus complets d'UNIX (créés avec un appel à fork()
). Vous travaillez peut-être également sur la concurrence entre plusieurs machines, auquel cas vos options de communication inter-thread sont considérablement plus limitées.
D'une 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 tas.
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é à l'aide de TlsAlloc et libéré à l'aide de TlsFree (vue d'ensemble 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 le handle du tas dans TLS. Ensuite, vous auriez quelque chose comme un "Thread-Local Heap". 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 assigner des «arènes» aux threads. Ceci est fait pour optimiser l'allocation pour plusieurs cœurs en réduisant la surcharge de synchronisation.
Sur le système d'exploitation FreeRTOS, les tâches (threads) partagent le même tas mais chacune d'elles a sa propre pile. Cela est très pratique lorsqu'il s'agit d'architectures de RAM à faible consommation d'énergie, car le même pool de mémoire peut être consulté / partagé par plusieurs threads, mais cela vient avec un petit problème, le développeur doit garder à l'esprit qu'un mécanisme de synchronisation de malloc et libre 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.