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?
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?
Risposte:
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.
you will get a stack overflow.
Un overflow dello stack su Stack Overflow!
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 .
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).
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?
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.
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.
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.