2009-11-03 11 views
103

Per quanto ne so, ogni thread ottiene uno stack distinto quando il thread viene creato dal sistema operativo. Mi chiedo se ogni thread ha un heap distinto anche da solo?I thread hanno un heap distinto?

+1

Quale piattaforma e libreria c? – divegeek

+0

sì, windows e linux, libreria c – root

+2

Bello. +1 mantieni le domande fondamentali in arrivo. –

risposta

110

No. Tutti i thread condividono un heap comune.

Ogni thread has a private stack, da cui è possibile aggiungere e rimuovere rapidamente elementi. Ciò rende la memoria basata sullo stack veloce, ma se si utilizza troppa memoria dello stack, come accade nella ricorsione infinita, si otterrà un overflow dello stack.

Poiché tutti i thread condividono lo stesso heap, l'accesso all'allocatore/deallocator deve essere sincronizzato. Esistono vari metodi e librerie per evitare allocator contention.

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

+0

Dipende dal runtime. – divegeek

+5

In genere i thread condividono le risorse, ad esempio la memoria, quindi qualsiasi implementazione di thread non-thread vorrebbe condividere l'heap. –

+10

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

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 vi sono i processi leggeri di Erlang e i processi full-on di UNIX (creati con una chiamata a fork()). Si potrebbe anche lavorare sulla concorrenza multi-macchina, nel qual caso le opzioni di comunicazione inter-thread sono notevolmente più limitate.

+0

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

+2

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

9

Per impostazione predefinita, C ha un solo heap.

Detto questo, alcuni allocatori che sono a conoscenza del thread ripartiranno l'heap in modo che ogni thread abbia la propria area da cui allocare. L'idea è che questo dovrebbe migliorare l'heap.

Un esempio di tale heap è Hoard.

+0

Per impostazione predefinita, C e C++ non hanno più thread. La specifica del C++ del 2003 almeno non lascia spazio ai thread nella sua progettazione di macchine virtuali, quindi i thread, in C++, sono definiti dall'implementazione. –

+0

Anche se diversi thread hanno aree diverse da allocare nell'heap, possono comunque vedere i dati allocati da un altro thread, quindi i thread condividono ancora lo stesso heap. Aggiornamento –

+1

: a partire da C++ 11 i thread non sono più definiti dall'implementazione. – anthropomorphic

3

Ogni thread ha il proprio stack e stack di chiamate.

Ogni thread condivide lo stesso heap.

1

In generale, tutti i thread utilizzano lo stesso spazio di indirizzi e, di conseguenza, hanno in genere un solo heap.

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

specifiche di Windows: TLS-spazio può essere assegnato utilizzando TlsAlloc e liberato mediante TlsFree (panoramica here). Di nuovo, non è un heap, solo DWORD.

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

EDIT: Alcuni allocatori memoria (specificamente jemalloc su FreeBSD) usa TLS per assegnare "arene" per filettature. Questo viene fatto per ottimizzare l'allocazione per più core riducendo l'overhead di sincronizzazione.

+0

> "Stranamente, Windows supporta più heap per processo.", Non è affatto strano, si potrebbero usare diversi heap per diversi tipi di allocazioni, solo aggiunge più flessibilità. Naturalmente puoi sempre arrivare a VirtualAlloc e costruire il tuo heap come vuoi tu. –

5

Dipende dal sistema operativo. Il runtime c standard su Windows e Unix utilizza un heap condiviso su thread. Questo significa bloccare ogni malloc/libero.

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. A mio avviso, il design di Symbian è migliore in quanto non solo elimina la necessità di bloccare durante alloc/free, ma incoraggia anche le specifiche pulite della proprietà dei dati tra i thread. Anche in questo caso, quando un thread muore, prende tutti gli oggetti che lo hanno allocato insieme ad esso - cioè non può perdere oggetti che ha allocato, che è una proprietà importante da avere nei dispositivi mobili con memoria vincolata.

Erlang segue anche un progetto simile in cui un "processo" funge da unità di garbage collection. Tutti i dati vengono comunicati tra processi mediante copia, ad eccezione dei blob binari che sono conteggiati con riferimento (credo).

2

Dipende da cosa intendi esattamente quando dici "mucchio".

Tutti i thread condividono lo spazio indirizzo, quindi gli oggetti allocati su heap sono accessibili da tutti i thread. Tecnicamente, anche gli stack sono condivisi in questo senso, ad esempio niente impedisce di accedere allo stack di altri thread (anche se non avrebbe quasi mai senso farlo).

D'altra parte, ci sono strutture heap utilizzate per allocare memoria. È qui che viene eseguita tutta la contabilità per l'allocazione della memoria 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 thread per un'eccellente spiegazione dei dettagli: How does malloc work in a multithreaded environment?

+0

+1: nessuno ha detto che anche lo stack (chiamata) è condiviso. – user2431763

1

On sistema operativo, FreeRTOS compiti (fili) condividono lo stesso mucchio ma ognuno di essi ha un proprio stack. Questo è molto utile quando si ha a che fare con architetture a bassa potenza di RAM bassa, perché è possibile accedere/condividere lo stesso pool di memoria da più thread, ma questo ha un piccolo problema, lo sviluppatore deve tenere presente che un meccanismo per sincronizzare malloc è necessario e gratuito, ecco perché è necessario utilizzare un qualche tipo di sincronizzazione/blocco del processo quando si assegna o si libera memoria nell'heap, ad esempio un semaforo o un mutex.