Czy wątki mają odrębną stertę?


114

O ile wiem, każdy wątek otrzymuje oddzielny stos, gdy wątek jest tworzony przez system operacyjny. Zastanawiam się, czy każdy wątek ma również własny stos?


tak, windows i linux, biblioteka c

3
Miły. +1 podtrzymuj te podstawowe pytania.

Odpowiedzi:


128

Nie. Wszystkie wątki mają wspólny stos.

Każdy wątek ma prywatny stos , z którego może szybko dodawać i usuwać elementy. To sprawia, że ​​pamięć oparta na stosie jest szybka, ale jeśli użyjesz zbyt dużej ilości pamięci stosu, jak to ma miejsce w przypadku nieskończonej rekurencji, nastąpi przepełnienie stosu.

Ponieważ wszystkie wątki współużytkują tę samą stertę, dostęp do alokatora / dezalokatora musi być zsynchronizowany. Istnieje wiele metod i bibliotek pozwalających uniknąć rywalizacji o alokatory .

Niektóre języki umożliwiają tworzenie prywatnych pul pamięci lub pojedynczych stert, które można przypisać do pojedynczego wątku.


5
Zwykle wątki współużytkują zasoby, takie jak pamięć, więc każda implementacja wątku innego niż braindead będzie współużytkować stertę.
R. Martinho Fernandes

10
Głównym powodem każdy wątek ma swój własny stos jest tak, że gwint może faktycznie coś zrobić (jak wezwać funkcje) ...
Edmund

3
Każdy wątek ma oddzielny stos, ale niekoniecznie jest „prywatny”. Inne wątki zwykle mają do niego dostęp.
zch

you will get a stack overflow.Przepełnienie stosu na Stack Overflow!
John Strood

2
@crisron Możliwe jest skonfigurowanie osobnej sterty dla każdego wątku, ale jeśli zrobisz to zamiast używać domyślnej sterty współdzielonej, wtedy np. wątkowi A trudno będzie przydzielić bufor, wypełnić go danymi i przekazać do wątku B i niech wątek B użyje danych, a następnie zwolni bufor (ponieważ wątek B nie ma dostępu do sterty wątku A, wątek B nie może zwolnić bufora; najlepszym wątkiem B jest przekazanie bufora z powrotem do wątku A ponownie i zwolnij wątek A).
Jeremy Friesner

9

Domyślnie C ma tylko jedną stertę.

To powiedziawszy, niektóre alokatory, które są świadome wątków, podzielą stertę na partycje, tak aby każdy wątek miał swój własny obszar do przydzielenia. Chodzi o to, że powinno to poprawić skalowanie sterty.

Jednym z przykładów takiej kupy jest Hoard .


Domyślnie C i C ++ nie mają wielu wątków. Specyfikacja C ++ z 2003 roku nie uwzględnia przynajmniej wątków w projekcie maszyny wirtualnej, więc wątki w języku c ++ są zdefiniowane jako implementacja.
Chris Becke

Nawet jeśli różne wątki mają różne obszary do przydzielenia na stercie, nadal mogą widzieć dane przydzielone przez inny wątek, więc wątki nadal współużytkują tę samą stertę.
Ken Bloom,

1
Aktualizacja: od wersji C ++ 11 wątki nie są już zdefiniowane jako implementacja.
Michael Dorst,

5

Zależy od systemu operacyjnego. Standardowe środowisko uruchomieniowe c w systemie Windows i unices wykorzystuje stertę współdzieloną między wątkami. Oznacza to zablokowanie każdego malloc / free.

Na przykład w systemie Symbian każdy wątek ma swoją własną stertę, chociaż wątki mogą udostępniać wskaźniki do danych przydzielonych w dowolnej stercie. Projekt Symbiana jest moim zdaniem lepszy, ponieważ nie tylko eliminuje potrzebę blokowania podczas przydzielania / zwolnienia, ale także zachęca do czystego określania własności danych między wątkami. Również w tym przypadku, gdy wątek umiera, zabiera wszystkie obiekty, które zaalokował wraz z nim - tj. Nie może wyciekać obiektów, które przydzielił, co jest ważną właściwością w urządzeniach mobilnych z ograniczoną pamięcią.

Erlang również stosuje podobny projekt, w którym „proces” działa jako jednostka usuwania śmieci. Wszystkie dane są przesyłane między procesami przez kopiowanie, z wyjątkiem binarnych obiektów blob, do których liczone są odwołania (tak mi się wydaje).


3

Każdy wątek ma swój własny stos i stos wywołań.

Każdy wątek ma tę samą stertę.


3

Zależy to od tego, co dokładnie masz na myśli, mówiąc „sterta”.

Wszystkie wątki współdzielą przestrzeń adresową, więc obiekty przydzielone na sterty są dostępne ze wszystkich wątków. Technicznie, stosy są również współdzielone w tym sensie, tj. Nic nie stoi na przeszkodzie, abyś uzyskał dostęp do stosu innego wątku (chociaż prawie nigdy nie miałoby to sensu).

Z drugiej strony istnieją struktury sterty używane do przydzielania pamięci. To tam odbywa się cała księgowość alokacji pamięci sterty. Struktury te są wyrafinowane, aby zminimalizować rywalizację między wątkami - więc niektóre wątki mogą mieć wspólną strukturę sterty (arenę), a niektóre mogą używać odrębnych aren.
Zobacz poniższy wątek, aby uzyskać doskonałe wyjaśnienie szczegółów: Jak działa malloc w środowisku wielowątkowym?


1

Zwykle wątki współużytkują stertę i inne zasoby, jednak istnieją konstrukcje podobne do wątków, które tego nie robią. Wśród tych wątkowych konstrukcji znajdują się lekkie procesy Erlanga i pełne procesy UNIX (tworzone za pomocą wywołania fork()). Możesz również pracować z współbieżnością wielu maszyn, w takim przypadku opcje komunikacji między wątkami są znacznie bardziej ograniczone.


Myślałem, że fork bardziej przypomina tworzenie nowego procesu, który po prostu kopiuje dane do nowej lokalizacji pamięci.
Jason Tholstrup

2
fork () może służyć w wielu przypadkach użycia, w których mogą być również używane wątki. Dzięki kopiowaniu przy zapisie nie ma znaczącej różnicy w kosztach w systemach uniksowych. Typowy przypadek użycia to sytuacja, w której pracownik jest autonomiczny (podobnie jak serwer WWW) od reszty usługi. Inną możliwością jest komunikacja poprzez stdin / out z głównym wątkiem / programem. fork () jest silna w Uniksie, podczas gdy inne platformy, takie jak Windows, preferują wątki. Prawdopodobnie głównym powodem jest to, że używanie fork () jest znacznie prostsze i bezpieczniejsze, a Unix ma tę filozofię prostoty. Zobacz na przykład serwer WWW Apache, z jego powolnym przejściem do wątków.
ypnos

1

Ogólnie rzecz biorąc, wszystkie wątki używają tej samej przestrzeni adresowej i dlatego zwykle mają tylko jedną stertę.

Jednak może to być nieco bardziej skomplikowane. Być może szukasz lokalnego magazynu wątków (TLS), ale przechowuje on tylko pojedyncze wartości.

Specyficzne dla systemu Windows: przestrzeń TLS można przydzielić za pomocą TlsAlloc i zwolnić za pomocą TlsFree (przegląd tutaj ). Ponownie, to nie jest kupa, tylko DWORDy.

O dziwo, system Windows obsługuje wiele stert na proces. Uchwyt Heap można przechowywać w TLS. Wtedy miałbyś coś takiego jak „Sterta lokalna wątku”. Jednak tylko uchwyt nie jest znany innym wątkom, nadal mogą uzyskać dostęp do jego pamięci za pomocą wskaźników, ponieważ nadal jest to ta sama przestrzeń adresowa.

EDYCJA : Niektóre alokatory pamięci (szczególnie jemalloc we FreeBSD) używają TLS do przypisywania „aren” do wątków. Ma to na celu zoptymalizowanie alokacji dla wielu rdzeni poprzez zmniejszenie obciążenia synchronizacji.


> „O dziwo, system Windows obsługuje wiele stosów na proces.”, To wcale nie jest dziwne, można by użyć różnych stosów dla różnych typów alokacji, po prostu dodaje większą elastyczność. Oczywiście zawsze możesz przejść do VirtualAlloc i zbudować własną stertę, jak chcesz.

1

W systemie operacyjnym FreeRTOS zadania (wątki) mają tę samą stertę, ale każde z nich ma swój własny stos. Jest to bardzo przydatne w przypadku architektur o niskim poborze mocy i małej pamięci RAM, ponieważ ta sama pula pamięci może być dostępna / współdzielona przez kilka wątków, ale wiąże się to z małym haczykiem, programista musi pamiętać, że mechanizm synchronizacji malloc i wolne jest potrzebne, dlatego konieczne jest użycie pewnego rodzaju synchronizacji / blokady procesu podczas przydzielania lub zwalniania pamięci na stercie, na przykład semafora lub muteksu.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.