Haben Threads einen bestimmten Haufen?


114

Soweit ich weiß, erhält jeder Thread einen eigenen Stapel, wenn der Thread vom Betriebssystem erstellt wird. Ich frage mich, ob jeder Thread auch einen eigenen Heap hat.


Ja, Windows und Linux, C-Bibliothek

3
Nett. +1 halten diese grundlegenden Fragen auf dem Laufenden.

Antworten:


128

Nein. Alle Threads haben einen gemeinsamen Heap.

Jeder Thread verfügt über einen privaten Stapel , über den Elemente schnell hinzugefügt und entfernt werden können. Dies macht den stapelbasierten Speicher schnell, aber wenn Sie zu viel Stapelspeicher verwenden, wie dies bei unendlicher Rekursion der Fall ist, kommt es zu einem Stapelüberlauf.

Da alle Threads denselben Heap verwenden, muss der Zugriff auf den Allokator / Deallocator synchronisiert werden. Es gibt verschiedene Methoden und Bibliotheken, um Allokatorkonflikte zu vermeiden .

In einigen Sprachen können Sie private Speicherpools oder einzelne Heaps erstellen, die Sie einem einzelnen Thread zuweisen können.


5
In der Regel teilen sich Threads Ressourcen wie Speicher, sodass jede Thread-Implementierung ohne Braindead den Heap gemeinsam nutzt.
R. Martinho Fernandes

10
Der Hauptgrund, warum jeder Thread seinen eigenen Stapel hat, ist, dass der Thread tatsächlich etwas tun kann (wie das Aufrufen von Funktionen) ...
Edmund

3
Jeder Thread hat einen separaten Stapel, der jedoch nicht unbedingt "privat" ist. Andere Threads dürfen normalerweise darauf zugreifen.
Zch

you will get a stack overflow.Ein Stapelüberlauf bei Stapelüberlauf!
John Strood

2
@crisron Es ist möglich, für jeden Thread einen eigenen Heap einzurichten. Wenn Sie dies jedoch tun, anstatt den gemeinsam genutzten Standardheap zu verwenden, wird es beispielsweise für Thread A schwierig, einen Puffer zuzuweisen, ihn mit Daten zu füllen und an Thread B zu übergeben und lassen Sie Thread B die Daten verwenden und dann den Puffer freigeben (da Thread B keinen Zugriff auf den Heap von Thread A hat, kann Thread B den Puffer nicht freigeben; das Beste, was Thread B tun kann, ist, den Puffer an Thread A zurückzugeben wieder und habe Thread A frei).
Jeremy Friesner

9

Standardmäßig hat C nur einen einzigen Heap.

Das heißt, einige Allokatoren, die Thread-fähig sind, partitionieren den Heap so, dass jeder Thread seinen eigenen Bereich zum Zuweisen hat. Die Idee ist, dass dies die Heap-Skala verbessern sollte.

Ein Beispiel für eine solche Haufen ist Hoard .


Standardmäßig haben C und C ++ nicht mehrere Threads. Die C ++ - Spezifikation von 2003 berücksichtigt zumindest keine Threads im Design der virtuellen Maschine, sodass Threads in C ++ implementierungsdefiniert sind.
Chris Becke

Selbst wenn verschiedene Threads unterschiedliche Bereiche auf dem Heap zuweisen müssen, können sie dennoch Daten sehen, die von einem anderen Thread zugewiesen wurden, sodass die Threads immer noch denselben Heap verwenden.
Ken Bloom

1
Update: Ab C ++ 11 sind Threads nicht mehr implementiert.
Michael Dorst

5

Hängt vom Betriebssystem ab. Die Standard-c-Laufzeit unter Windows und Unices verwendet einen gemeinsam genutzten Heap über Threads hinweg. Dies bedeutet, dass jeder Malloc / Free gesperrt wird.

Unter Symbian verfügt beispielsweise jeder Thread über einen eigenen Heap, obwohl Threads Zeiger auf Daten gemeinsam nutzen können, die in einem beliebigen Heap zugewiesen sind. Das Design von Symbian ist meiner Meinung nach besser, da es nicht nur das Sperren während der Zuweisung / Freigabe überflüssig macht, sondern auch eine saubere Angabe des Datenbesitzes zwischen Threads fördert. Auch in diesem Fall nimmt ein Thread, wenn er stirbt, alle ihm zugewiesenen Objekte mit, dh er kann keine zugewiesenen Objekte verlieren, was eine wichtige Eigenschaft bei Mobilgeräten mit eingeschränktem Speicher ist.

Erlang folgt auch einem ähnlichen Design, bei dem ein "Prozess" als Einheit der Speicherbereinigung fungiert. Alle Daten werden zwischen Prozessen durch Kopieren übertragen, mit Ausnahme von binären Blobs, die als Referenz gezählt werden (glaube ich).


3

Jeder Thread hat seinen eigenen Stack und Call-Stack.

Jeder Thread teilt sich den gleichen Heap.


3

Es hängt davon ab, was Sie genau meinen, wenn Sie "Haufen" sagen.

Alle Threads teilen sich den Adressraum, sodass auf Heap-zugewiesene Objekte von allen Threads aus zugegriffen werden kann. Technisch gesehen werden Stapel auch in diesem Sinne gemeinsam genutzt, dh nichts hindert Sie daran, auf den Stapel anderer Threads zuzugreifen (obwohl dies fast nie sinnvoll wäre).

Andererseits gibt es Heap- Strukturen, die zum Zuweisen von Speicher verwendet werden. Hier erfolgt die gesamte Buchhaltung für die Zuordnung des Heapspeichers. Diese Strukturen sind ausgefeilt organisiert, um Konflikte zwischen den Threads zu minimieren. Einige Threads teilen sich möglicherweise eine Heap-Struktur (eine Arena), andere verwenden möglicherweise unterschiedliche Arenen.
Im folgenden Thread finden Sie eine hervorragende Erklärung der Details: Wie funktioniert malloc in einer Multithread-Umgebung?


1

In der Regel teilen sich Threads den Heap und andere Ressourcen, es gibt jedoch threadähnliche Konstruktionen, die dies nicht tun. Zu diesen threadähnlichen Konstruktionen gehören Erlangs Lightweight-Prozesse und UNIXs Full-On-Prozesse (erstellt mit einem Aufruf von fork()). Möglicherweise arbeiten Sie auch an der Parallelität mehrerer Computer. In diesem Fall sind Ihre Kommunikationsoptionen zwischen Threads erheblich eingeschränkter.


Ich dachte, Fork wäre eher so, als würde man einen neuen Prozess erstellen, bei dem die Daten einfach an einen neuen Speicherort kopiert werden.
Jason Tholstrup

2
fork () kann in vielen Anwendungsfällen verwendet werden, in denen auch Threads verwendet werden können. Aufgrund von Copy-on-Write gibt es auf Unix-Systemen keinen signifikanten Kostenunterschied. Ein typischer Anwendungsfall ist, wenn der Worker vom Rest des Dienstes autonom ist (wie ein Webserver). Eine andere Möglichkeit besteht darin, über stdin / out mit dem Hauptthread / -programm zu kommunizieren. fork () ist unter Unix stark, während andere Plattformen wie Windows Threading bevorzugen. Der Hauptgrund ist wahrscheinlich, dass die Verwendung von fork () viel einfacher und sicherer ist und Unix diese Einfachheitstheorie hat. Siehe zum Beispiel den Apache-Webserver mit seinem langsamen Übergang zu Threads.
Ypnos

1

Im Allgemeinen verwenden alle Threads denselben Adressraum und haben daher normalerweise nur einen Heap.

Es kann jedoch etwas komplizierter sein. Möglicherweise suchen Sie nach TLS ( Thread Local Storage ), es werden jedoch nur einzelne Werte gespeichert.

Windows-spezifische: TLS-Raum kann mit zugewiesen TlsAlloc und befreit mit TlsFree (Übersicht hier ). Auch hier ist es kein Haufen, nur DWORDs.

Seltsamerweise unterstützt Windows mehrere Heaps pro Prozess. Man kann das Handle des Heaps in TLS speichern. Dann hätten Sie so etwas wie einen "Thread-Local Heap". Nur das Handle ist den anderen Threads nicht bekannt. Sie können dennoch mithilfe von Zeigern auf den Speicher zugreifen, da es sich immer noch um denselben Adressraum handelt.

BEARBEITEN : Einige Speicherzuweiser (insbesondere jemalloc unter FreeBSD) verwenden TLS, um Threads "Arenen" zuzuweisen. Dies wird durchgeführt, um die Zuordnung für mehrere Kerne zu optimieren, indem der Synchronisationsaufwand verringert wird.


> "Seltsamerweise unterstützt Windows mehrere Heaps pro Prozess.", Es ist überhaupt nicht seltsam, man könnte verschiedene Heaps für verschiedene Arten von Zuordnungen verwenden, sondern erhöht nur die Flexibilität. Natürlich können Sie jederzeit zu VirtualAlloc wechseln und Ihren eigenen Heap erstellen, wie Sie möchten.

1

Unter dem FreeRTOS-Betriebssystem teilen sich Aufgaben (Threads) denselben Heap, aber jeder von ihnen hat seinen eigenen Stapel. Dies ist sehr praktisch, wenn es um Architekturen mit geringem Stromverbrauch und geringem Arbeitsspeicher geht, da mehrere Threads auf denselben Speicherpool zugreifen / ihn gemeinsam nutzen können. Dies ist jedoch mit einem kleinen Haken verbunden. Der Entwickler muss berücksichtigen, dass ein Mechanismus zum Synchronisieren von Malloc vorhanden ist und frei ist erforderlich, deshalb ist es notwendig, eine Art Prozesssynchronisation / -sperre zu verwenden, wenn Speicher auf dem Heap zugewiesen oder freigegeben wird, beispielsweise ein Semaphor oder ein Mutex.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.