2009-11-03 5 views
103

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

+1

Welche Plattform und C-Bibliothek? – divegeek

+0

ja, Windows und Linux, c Bibliothek – root

+2

Nizza. +1 halten diese grundlegenden Fragen kommen. –

Antwort

110

Nein. Alle Threads teilen sich einen gemeinsamen Heap.

Jede thread has a private stack, die es schnell hinzufügen und entfernen können. Dies macht Stapelspeicher schnell, aber wenn Sie zu viel Stapelspeicher verwenden, wie in unendlicher Rekursion auftritt, erhalten Sie einen Stapelüberlauf.

Da alle Threads den gleichen Heapspeicher haben, muss der Zugriff auf den Zuordner/Aufteiler synchronisiert werden. Es gibt verschiedene Methoden und Bibliotheken zur Vermeidung von allocator contention.

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

+0

Das hängt von der Laufzeit ab. – divegeek

+5

In der Regel teilen sich Threads Ressourcen, z. B. Arbeitsspeicher, sodass alle Nicht-Braindead-Thread-Implementierungen den Heap teilen. –

+10

Der * Haupt * Grund, dass jeder Thread seinen eigenen Stack hat, ist so, dass der Thread tatsächlich etwas tun kann (wie Funktionen aufrufen) ... – Edmund

1

Gewöhnlich teilen Threads den Heap und andere Ressourcen, jedoch gibt es Thread-ähnliche Konstruktionen, die das nicht tun. Zu diesen Thread-ähnlichen Konstruktionen gehören die leichten Prozesse von Erlang und die vollständigen Prozesse von UNIX (erstellt mit einem Aufruf an fork()). Möglicherweise arbeiten Sie auch an der Gleichzeitigkeit von mehreren Computern. In diesem Fall sind Ihre Inter-Thread-Kommunikationsoptionen wesentlich eingeschränkter.

+0

Ich dachte, Gabel war eher wie Erstellen eines neuen Prozesses, der nur die Daten an einen neuen Speicherort kopiert. –

+2

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

9

Standardmäßig hat C nur einen einzigen Heap.

Das heißt, einige Zuordner, die Threads bewusst sind, werden den Heap so partitionieren, dass jedem Thread ein eigener Bereich zugewiesen werden muss. Die Idee ist, dass dies den Haufen besser skalieren sollte.

Ein Beispiel für einen solchen Heap ist Hoard.

+0

Standardmäßig haben C und C++ nicht mehrere Threads. Die C++ - Spezifikation von 2003 berücksichtigt Threads im Design virtueller Maschinen zumindest nicht, sodass Threads in C++ als Implementierung definiert sind. –

+0

Auch wenn verschiedene Threads unterschiedliche Bereiche für die Zuweisung auf dem Heap haben, können sie dennoch Daten sehen, die von einem anderen Thread zugewiesen wurden, sodass die Threads immer noch denselben Heap teilen. –

+1

Update: ab C++ 11 Threads sind nicht mehr implementiert. – anthropomorphic

3

Jeder Thread hat seinen eigenen Stack und Call-Stack.

Jeder Thread teilt den gleichen Heap.

1

Im Allgemeinen verwenden alle Threads den gleichen Adressraum und haben deshalb normalerweise nur einen Heap.

Es kann jedoch ein bisschen komplizierter sein. Sie suchen möglicherweise nach Thread Local Storage (TLS), aber es speichert nur einzelne Werte.

Windows-spezifische: TLS-Raum zugeordnet werden kann TlsAlloc und befreit mit TlsFree (Übersicht here) verwendet wird. Wiederum ist es kein Heap, nur DWORDs.

Komischerweise unterstützt Windows mehrere Heaps pro Prozess. Man kann den Griff des Heaps in TLS speichern. Dann hätten Sie so etwas wie einen "Thread-Local Heap". Jedoch ist nur das Handle den anderen Threads nicht bekannt, sie können immer noch mit Zeigern auf ihren Speicher zugreifen, da es immer noch denselben Adressraum hat.

EDIT: Einige Speicherverteilern (speziell jemalloc auf FreeBSD) verwenden TLS "Arenen" auf Threads zugewiesen werden. Dies wird getan, um die Zuweisung für mehrere Kerne zu optimieren, indem der Synchronisationsaufwand verringert wird.

+0

> "Seltsam, Windows unterstützt mehrere Heaps pro Prozess.", Es ist überhaupt nicht komisch, könnte man verschiedene Heaps für verschiedene Arten von Zuordnungen verwenden, fügt nur mehr Flexibilität hinzu. Natürlich können Sie immer auf VirtualAlloc zugreifen und Ihren eigenen Heap erstellen, wie Sie wollen. –

5

Hängt vom Betriebssystem ab. Die Standard-c-Laufzeit für Windows und Unices verwendet einen gemeinsamen Heap über Threads hinweg. Dies bedeutet, dass jedes malloc/free gesperrt wird.

Auf Symbian zum Beispiel kommt jeder Thread mit einem eigenen Heap, obwohl Threads Zeiger auf Daten teilen können, die in einem beliebigen Heap zugeordnet sind. Das Design von Symbian ist meiner Meinung nach besser, da es nicht nur die Notwendigkeit der Sperrung während allok/free beseitigt, sondern auch eine saubere Spezifikation der Dateneigentümerschaft unter Threads fördert. Auch in diesem Fall, wenn ein Thread stirbt, nimmt er alle Objekte mit, die er zugeordnet hat - d. H. Er kann keine Objekte verlieren, die er zugewiesen hat, was eine wichtige Eigenschaft in mobilen Geräten mit beschränktem Speicher ist.

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

2

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

Alle Threads teilen sich den Adressraum, daher können auf Heap allokierte Objekte von allen Threads aus zugegriffen werden. Technisch gesehen werden Stacks in diesem Sinne ebenfalls geteilt, d. H. Nichts hindert Sie daran, auf den Stack eines anderen Threads zuzugreifen (obwohl dies fast nie sinnvoll wäre).

Auf der anderen Seite gibt es Heap Strukturen verwendet, um Speicher zuzuordnen. Dort wird die gesamte Buchhaltung für die Heap-Speicherzuweisung ausgeführt. Diese Strukturen sind hochentwickelt, um Konflikte zwischen den Threads zu minimieren - also können sich einige Threads eine Heap-Struktur (eine Arena) teilen, und einige können unterschiedliche Arenen verwenden.
Siehe folgende Gewinde für eine ausgezeichnete Erklärung der Details: How does malloc work in a multithreaded environment?

+0

+1: Niemand hat gesagt, dass (Call) Stack auch geteilt wird. – user2431763

1

Auf FreeRTOS Betriebssystem, Aufgaben (Threads) die gleichen Haufen teilen, aber jeder von ihnen hat einen eigenen Stapel. Dies ist sehr praktisch, wenn es um Low-Power-Low-RAM-Architekturen geht, da auf denselben Speicherpool mehrere Threads zugreifen können. Dies ist jedoch mit einem kleinen Haken verbunden. Der Entwickler muss einen Mechanismus zum Synchronisieren von malloc berücksichtigen und free ist erforderlich, deshalb ist es notwendig, eine Art von Prozesssynchronisierung/-sperre zu verwenden, wenn Speicher auf dem Heap zugewiesen oder freigegeben wird, zum Beispiel ein Semaphor oder ein Mutex.