Apakah utas memiliki heap yang berbeda?

114

Sejauh yang saya tahu setiap utas mendapatkan tumpukan yang berbeda ketika utas dibuat oleh sistem operasi. Saya ingin tahu apakah setiap utas memiliki tumpukan yang berbeda untuk dirinya sendiri juga?

Martin Thoma
sumber
ya, windows dan linux, perpustakaan c
3
Bagus. +1 teruskan pertanyaan mendasar itu.

Jawaban:

128

Tidak. Semua utas berbagi tumpukan yang sama.

Setiap utas memiliki tumpukan pribadi , yang dapat dengan cepat menambah dan menghapus item. Ini membuat memori berbasis tumpukan cepat, tetapi jika Anda menggunakan terlalu banyak memori tumpukan, seperti yang terjadi dalam rekursi tak terbatas, Anda akan mendapatkan tumpukan melimpah.

Karena semua utas berbagi heap yang sama, akses ke pengalokasi / deallocator harus disinkronkan. Ada berbagai metode dan pustaka untuk menghindari perselisihan pengalokasi .

Beberapa bahasa memungkinkan Anda membuat kumpulan memori pribadi, atau tumpukan individu, yang dapat Anda tetapkan ke satu utas.

brianegge.dll
sumber
5
Biasanya thread berbagi resource, seperti memori, sehingga implementasi thread non-braindead akan membagikan heap.
R. Martinho Fernandes
10
The utama alasan setiap thread memiliki stack sendiri adalah agar benang dapat benar-benar melakukan sesuatu (seperti panggilan fungsi) ...
Edmund
3
Setiap utas memiliki tumpukan terpisah, tetapi belum tentu 'pribadi'. Utas lain biasanya diizinkan untuk mengaksesnya.
zch
you will get a stack overflow.Stack overflow di Stack Overflow!
John Strood
2
@crisron Anda dapat menyiapkan heap terpisah untuk setiap utas, tetapi jika Anda melakukannya daripada menggunakan heap bersama default, maka akan sulit bagi misalnya utas A untuk mengalokasikan buffer, mengisinya dengan data, meneruskannya ke utas B , dan meminta utas B menggunakan data dan kemudian membebaskan buffer (karena utas B tidak memiliki akses ke tumpukan utas A, utas B tidak dapat membebaskan buffer; utas B terbaik yang bisa dilakukan adalah mengembalikan buffer ke utas A lagi dan bebaskan thread A).
Jeremy Friesner
9

Secara default, C hanya memiliki satu heap.

Meskipun demikian, beberapa pengalokasi yang sadar thread akan mempartisi heap sehingga setiap thread memiliki area sendiri untuk dialokasikan. Idenya adalah ini harus membuat skala heap lebih baik.

Salah satu contoh tumpukan tersebut adalah Hoard .

R Samuel Klatchko
sumber
Secara default C, dan C ++, tidak memiliki banyak utas. Spesifikasi 2003 c ++ setidaknya tidak memberikan kelonggaran untuk utas dalam desain mesin virtualnya, jadi utas, dalam c ++, didefinisikan implementasi.
Chris Becke
Meskipun thread yang berbeda memiliki area yang berbeda untuk dialokasikan di heap, mereka masih dapat melihat data yang dialokasikan oleh thread lain, jadi thread tersebut masih berbagi heap yang sama.
Ken Bloom
1
Pembaruan: sejak utas C ++ 11 implementasi tidak lagi ditentukan.
Michael Dorst
5

Tergantung pada OS-nya. Runtime c standar pada windows dan unices menggunakan heap bersama di seluruh thread. Ini berarti mengunci setiap malloc / gratis.

Di Symbian, misalnya, setiap utas dilengkapi dengan heapnya sendiri, meskipun utas dapat membagikan petunjuk ke data yang dialokasikan di heap mana pun. Desain Symbian lebih baik menurut saya karena tidak hanya menghilangkan kebutuhan penguncian selama alokasi / bebas, tetapi juga mendorong spesifikasi kepemilikan data yang bersih di antara utas. Juga dalam kasus ketika utas mati, ia mengambil semua objek yang dialokasikan bersamanya - yaitu tidak dapat membocorkan objek yang telah dialokasikan, yang merupakan properti penting untuk dimiliki di perangkat seluler dengan memori terbatas.

Erlang juga mengikuti desain serupa di mana "proses" bertindak sebagai unit pengumpulan sampah. Semua data dikomunikasikan antara proses dengan menyalin, kecuali untuk blob biner yang referensi dihitung (saya pikir).

Srikumar
sumber
3

Setiap utas memiliki tumpukan dan tumpukan panggilannya sendiri.

Setiap utas berbagi tumpukan yang sama.

tsalter
sumber
3

Tergantung pada apa yang Anda maksud saat mengucapkan "heap".

Semua utas berbagi ruang alamat, jadi objek dengan alokasi heap dapat diakses dari semua utas. Secara teknis, tumpukan juga dibagikan dalam pengertian ini, yaitu tidak ada yang mencegah Anda mengakses tumpukan utas lain (meskipun hampir tidak masuk akal untuk melakukannya).

Di sisi lain, ada struktur heap yang digunakan untuk mengalokasikan memori. Di situlah semua pembukuan untuk alokasi memori heap dilakukan. Struktur ini diatur secara canggih untuk meminimalkan perselisihan di antara utas - jadi beberapa utas mungkin berbagi struktur heap (arena), dan beberapa mungkin menggunakan arena yang berbeda.
Lihat utas berikut untuk penjelasan yang sangat baik tentang detailnya: Bagaimana malloc bekerja di lingkungan multithread?

VladV
sumber
1

Biasanya, utas berbagi heap dan sumber daya lainnya, namun ada konstruksi seperti utas yang tidak. Di antara konstruksi seperti utas ini adalah proses ringan Erlang, dan proses lengkap UNIX (dibuat dengan panggilan ke fork()). Anda mungkin juga bekerja pada konkurensi multi-mesin, dalam hal ini opsi komunikasi antar-utas Anda jauh lebih terbatas.

Ken Bloom
sumber
Saya pikir garpu lebih seperti membuat proses baru yang baru saja menyalin data ke lokasi memori baru.
Jason Tholstrup
2
fork () bisa berfungsi dalam banyak kasus penggunaan di mana utas juga dapat digunakan. Karena copy-on-write, tidak ada perbedaan biaya yang signifikan pada sistem Unix. Kasus penggunaan tipikal adalah saat pekerja bersifat otonom (seperti server web) dari bagian layanan lainnya. Kemungkinan lain adalah berkomunikasi melalui stdin / out dengan utas / program utama. fork () kuat di Unix, sedangkan platform lain seperti Windows lebih suka threading. Alasan utamanya mungkin adalah bahwa menggunakan fork () jauh lebih sederhana dan lebih aman dan Unix memiliki filosofi kesederhanaan ini. Lihat misalnya server web apache, dengan transisi yang lambat ke utas.
ypnos
1

Secara umum, semua utas menggunakan ruang alamat yang sama dan oleh karena itu biasanya hanya memiliki satu tumpukan.

Namun, ini bisa sedikit lebih rumit. Anda mungkin mencari Thread Local Storage (TLS), tetapi hanya menyimpan nilai tunggal.

Khusus Windows: TLS-space dapat dialokasikan menggunakan TlsAlloc dan dibebaskan menggunakan TlsFree (Ringkasan di sini ). Sekali lagi, ini bukan heap, hanya DWORD.

Anehnya, Windows mendukung banyak Heaps per proses. Seseorang dapat menyimpan pegangan Heap di TLS. Kemudian Anda akan memiliki sesuatu seperti "Thread-Local Heap". Namun, hanya pegangan yang tidak diketahui oleh utas lainnya, mereka masih dapat mengakses memorinya menggunakan pointer karena ruang alamatnya masih sama.

EDIT : Beberapa pengalokasi memori (khususnya jemalloc di FreeBSD) menggunakan TLS untuk menetapkan "arena" ke utas. Ini dilakukan untuk mengoptimalkan alokasi untuk beberapa inti dengan mengurangi overhead sinkronisasi.

Meinersbur
sumber
> "Anehnya, Windows mendukung banyak Heaps per proses.", Itu tidak aneh sama sekali, seseorang dapat menggunakan heaps yang berbeda untuk tipe alokasi yang berbeda, hanya menambahkan lebih banyak fleksibilitas. Tentu saja Anda selalu dapat membuka VirtualAlloc, dan membuat heap Anda sendiri sesuka Anda.
1

Pada sistem Operasi FreeRTOS, tugas (utas) berbagi tumpukan yang sama tetapi masing-masing memiliki tumpukannya sendiri. Ini sangat berguna ketika berhadapan dengan arsitektur RAM rendah daya rendah, karena kumpulan memori yang sama dapat diakses / dibagikan oleh beberapa utas, tetapi ini hadir dengan sedikit tangkapan, pengembang perlu mengingat bahwa mekanisme untuk menyinkronkan malloc dan gratis diperlukan, itulah mengapa perlu menggunakan beberapa jenis sinkronisasi proses / kunci saat mengalokasikan atau membebaskan memori di heap, misalnya semaphore atau mutex.

Noreddine -Kessa
sumber