I thread hanno un mucchio distinto?


114

Per quanto ne so, ogni thread ottiene uno stack distinto quando il thread viene creato dal sistema operativo. Mi chiedo se ogni thread ha anche un mucchio distinto a se stesso?


sì, windows e linux, libreria c

3
Bello. +1 continua a far arrivare quelle domande fondamentali.

Risposte:


128

No. Tutti i thread condividono un mucchio comune.

Ogni thread ha uno stack privato , dal quale può aggiungere e rimuovere rapidamente elementi. Questo rende veloce la memoria basata sullo stack, ma se usi troppa memoria dello stack, come accade nella ricorsione infinita, otterrai un overflow dello stack.

Poiché tutti i thread condividono lo stesso heap, è necessario sincronizzare l'accesso all'allocatore / deallocatore. Esistono vari metodi e librerie per evitare la contesa degli allocatori .

Alcuni linguaggi consentono di creare pool privati ​​di memoria o singoli heap, che è possibile assegnare a un singolo thread.


5
In genere i thread condividono risorse, come la memoria, quindi qualsiasi implementazione di thread non braindead condividerebbe l'heap.
R. Martinho Fernandes

10
Il motivo principale per cui ogni thread ha il proprio stack è che il thread può effettivamente fare qualcosa (come chiamare una funzione) ...
Edmund

3
Ogni thread ha uno stack separato, ma non è necessariamente "privato". Gli altri thread sono generalmente autorizzati ad accedervi.
zch

you will get a stack overflow.Un overflow dello stack su Stack Overflow!
John Strood

2
@crisron È possibile impostare un heap separato per ogni thread, ma se lo fai invece di usare l'heap condiviso predefinito, allora diventa difficile per esempio il thread A allocare un buffer, riempirlo di dati, passarlo al thread B e fare in modo che il thread B utilizzi i dati e quindi liberi il buffer (poiché il thread B non ha accesso all'heap del thread A, il thread B non può liberare il buffer; il miglior thread che B potrebbe fare è restituire il buffer al thread A di nuovo e fai in modo che il thread A lo liberi).
Jeremy Friesner

9

Per impostazione predefinita, C ha solo un singolo heap.

Detto questo, alcuni allocatori che riconoscono i thread partizioneranno l'heap in modo che ogni thread abbia la propria area da cui allocare. L'idea è che questo dovrebbe migliorare la scalabilità dell'heap.

Un esempio di un tale mucchio è Hoard .


Per impostazione predefinita, C e C ++ non hanno più thread. La specifica c ++ 2003 almeno non tiene conto dei thread nella progettazione della macchina virtuale, quindi i thread, in c ++, sono definiti come implementazione.
Chris Becke

Anche se thread diversi hanno aree diverse da allocare dall'heap, possono comunque vedere i dati allocati da un altro thread, quindi i thread condividono comunque lo stesso heap.
Ken Bloom

1
Aggiornamento: a partire da C ++ 11 i thread non sono più definiti come implementazione.
Michael Dorst

5

Dipende dal sistema operativo. Il runtime c standard su windows e unices utilizza un heap condiviso tra i thread. Ciò significa bloccare ogni malloc / free.

Su Symbian, ad esempio, ogni thread viene fornito con il proprio heap, sebbene i thread possano condividere i puntatori ai dati allocati in qualsiasi heap. Il design di Symbian è migliore a mio parere poiché non solo elimina la necessità di bloccare durante alloc / free, ma incoraggia anche una specifica pulita della proprietà dei dati tra i thread. Anche in quel caso quando un thread muore, prende tutti gli oggetti che ha allocato insieme ad esso - cioè non può perdere oggetti che ha allocato, che è una proprietà importante da avere nei dispositivi mobili con memoria limitata.

Erlang segue anche una struttura simile in cui un "processo" funge da unità di raccolta dei rifiuti. Tutti i dati vengono comunicati tra i processi mediante copia, ad eccezione dei BLOB binari che vengono contati come riferimento (credo).


3

Ogni thread ha il proprio stack e stack di chiamate.

Ogni thread condivide lo stesso heap.


3

Dipende da cosa intendi esattamente quando dici "mucchio".

Tutti i thread condividono lo spazio degli indirizzi, quindi gli oggetti allocati nell'heap sono accessibili da tutti i thread. Tecnicamente, anche gli stack sono condivisi in questo senso, cioè nulla ti impedisce di accedere allo stack di altri thread (anche se non avrebbe quasi mai senso farlo).

D'altra parte, ci sono strutture di heap utilizzate per allocare la memoria. È qui che viene eseguita tutta la contabilità per l'allocazione della memoria dell'heap. Queste strutture sono organizzate in modo sofisticato per ridurre al minimo la contesa tra i thread, quindi alcuni thread potrebbero condividere una struttura heap (un'arena) e alcuni potrebbero utilizzare arene distinte.
Vedere il seguente thread per un'eccellente spiegazione dei dettagli: Come funziona malloc in un ambiente multithread?


1

In genere, i thread condividono l'heap e altre risorse, tuttavia esistono costruzioni simili a thread che non lo fanno. Tra queste costruzioni filiformi ci sono i processi leggeri di Erlang ei processi full-on di UNIX (creati con una chiamata a fork()). Potresti anche lavorare sulla concorrenza multi-macchina, nel qual caso le tue opzioni di comunicazione tra thread sono notevolmente più limitate.


Pensavo che fork fosse più come creare un nuovo processo che copiava i dati in una nuova posizione di memoria.
Jason Tholstrup

2
fork () può servire in molti casi d'uso in cui possono essere usati anche i thread. A causa del copy-on-write, non vi è alcuna differenza di costo significativa sui sistemi Unix. Il caso d'uso tipico è quello in cui il lavoratore è autonomo (come il server web) dal resto del servizio. Un'altra possibilità è quella di comunicare tramite stdin / out con il thread / programma principale. fork () è forte su Unix, mentre altre piattaforme come Windows preferiscono il threading. La ragione principale probabilmente è che usare fork () è molto più semplice e sicuro e Unix ha questa filosofia di semplicità. Vedi ad esempio Apache webserver, con la sua lenta transizione ai thread.
ypnos

1

In generale, tutti i thread utilizzano lo stesso spazio degli indirizzi e quindi di solito hanno un solo heap.

Tuttavia, può essere un po 'più complicato. Potresti cercare Thread Local Storage (TLS), ma memorizza solo valori singoli.

Specifico per Windows: lo spazio TLS può essere allocato utilizzando TlsAlloc e liberato utilizzando TlsFree (Panoramica qui ). Ancora una volta, non è un mucchio, solo DWORD.

Stranamente, Windows supporta più Heap per processo. Si può memorizzare l'handle dell'heap in TLS. Allora avresti qualcosa come un "Thread-Local Heap". Tuttavia, solo l'handle non è noto agli altri thread, possono comunque accedere alla sua memoria utilizzando i puntatori poiché è ancora lo stesso spazio degli indirizzi.

EDIT : Alcuni allocatori di memoria (in particolare jemalloc su FreeBSD) usano TLS per assegnare "arene" ai thread. Ciò viene fatto per ottimizzare l'allocazione per più core riducendo il sovraccarico di sincronizzazione.


> "Stranamente, Windows supporta più heap per processo.", Non è affatto strano, si potrebbero utilizzare diversi heap per diversi tipi di allocazioni, aggiunge solo maggiore flessibilità. Ovviamente puoi sempre passare a VirtualAlloc e creare il tuo heap come preferisci.

1

Sul sistema operativo FreeRTOS, le attività (thread) condividono lo stesso heap ma ognuna di esse ha il proprio stack. Questo è molto utile quando si ha a che fare con architetture a basso consumo di RAM, perché lo stesso pool di memoria può essere raggiunto / condiviso da più thread, ma questo ha un piccolo problema, lo sviluppatore deve tenere presente che un meccanismo per sincronizzare malloc e free è necessario, ecco perché è necessario utilizzare un qualche tipo di sincronizzazione / blocco del processo quando si alloca o si libera memoria sull'heap, ad esempio un semaforo o un mutex.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.