Наскільки мені відомо, кожен потік отримує чіткий стек, коли нитка створена операційною системою. Цікаво, чи кожна з ниток також відрізняє купу?
Наскільки мені відомо, кожен потік отримує чіткий стек, коли нитка створена операційною системою. Цікаво, чи кожна з ниток також відрізняє купу?
Відповіді:
Ні. Усі нитки мають спільну купу.
Кожна нитка має приватний стек , до якого можна швидко додавати та видаляти елементи. Це робить пам'ять на основі стека швидкою, але якщо ви використовуєте занадто багато пам'яті стека, як це відбувається в нескінченній рекурсії, ви отримаєте переповнення стека.
Оскільки всі потоки мають однакову групу, доступ до розподільника / оператора повинен бути синхронізований. Існують різні методи та бібліотеки для уникнення суперечок розподільника .
Деякі мови дозволяють створювати приватні пули пам’яті або окремі купи, які ви можете призначити одному потоку.
you will get a stack overflow.
Переповнення стека на Stack Overflow!
За замовчуванням C має лише одну купу.
З цього приводу, деякі алокатори, які знають потоки, поділять купу, щоб у кожного потоку була виділена власна область. Ідея полягає в тому, що це повинно покращити масштаб купи.
Одним із прикладів такої купи є Хоард .
Залежить від ОС. Стандартний час виконання c для Windows та Unices використовує спільну купу по потоках. Це означає заблокувати кожен малак / вільний.
Наприклад, у Symbian кожен потік має свою власну купу, хоча потоки можуть обмінюватися покажчиками на дані, виділені в будь-якій купі. На мою думку, дизайн Symbian є кращим, оскільки він не тільки виключає необхідність блокування під час allo / free, але також заохочує чітку специфікацію права власності на дані серед потоків. Також у тому випадку, коли нитка відмирає, вона бере всі виділені разом із нею об’єкти - тобто вона не може просочувати виділені нею об'єкти, що є важливою властивістю мати в мобільних пристроях із обмеженою пам'яттю.
Ерланг також дотримується подібної конструкції, коли «процес» виступає як одиниця збору сміття. Усі дані передаються між процесами шляхом копіювання, за винятком бінарних крапок, які посилаються на посилання (я думаю).
Це залежить від того, що саме ви маєте на увазі, говорячи "купи".
Усі потоки поділяють адресний простір, тому об'єкти, виділені з купи, доступні з усіх потоків. У технічному плані стеки поділяються також у цьому сенсі, тобто ніщо не заважає вам отримати доступ до стека інших потоків (хоча це майже ніколи не має сенсу).
З іншого боку, є купа структур , що використовуються для виділення пам'яті. Саме тут і ведеться вся бухгалтерія з розподілу пам'яті купи. Ці структури є складно організованими, щоб мінімізувати суперечки між нитками - тому деякі потоки можуть мати спільну структуру (арену), а деякі можуть використовувати окремі арени.
Дивіться наступну нитку для відмінного пояснення деталей: Як працює malloc у багатопотоковому середовищі?
Зазвичай нитки діляться нагромадженням та іншими ресурсами, однак є ниткоподібні конструкції, які цього не роблять. Серед цих ниткоподібних конструкцій - легкі процеси Ерланга та повні процеси UNIX (створені із закликом до fork()
). Можливо, ви також працюєте над одночасністю багатомашинних версій, і в цьому випадку ваші варіанти комунікації між потоками значно обмежені.
Взагалі кажучи, всі потоки використовують один і той же адресний простір і тому зазвичай мають лише одну купу.
Однак це може бути трохи складніше. Ви можете шукати локальне зберігання потоків (TLS), але воно зберігає лише окремі значення.
Спеціально для Windows: TLS-простір можна виділити за допомогою TlsAlloc та звільнити за допомогою TlsFree (Огляд тут ). Знову ж таки, це не купа, а лише DWORD.
Як не дивно, Windows підтримує кілька Купи в процесі. Ручку Heap можна зберігати в TLS. Тоді у вас вийшло б щось на кшталт "Тема-локальна купа". Однак просто ручка не відома іншим потокам, вони все ще можуть отримати доступ до її пам'яті за допомогою покажчиків, оскільки це все той же адресний простір.
EDIT : Деякі алокатори пам'яті (зокрема jemalloc у FreeBSD) використовують TLS для присвоєння "арен" потокам. Це робиться для оптимізації розподілу для декількох ядер шляхом зменшення накладних витрат синхронізації.
У операційній системі FreeRTOS завдання (потоки) поділяють ту саму купу, але кожна з них має власний стек. Це дуже зручно при роботі з архітектурами з низькою потужністю оперативної пам’яті з низькою потужністю, оскільки до одного і того ж пулу пам’яті можна отримати доступ / поділитися декількома потоками, але це має невеликий улов, розробнику потрібно пам’ятати, що існує механізм синхронізації malloc і вільний потрібен, тому необхідно використовувати певний тип синхронізації / блокування процесу при розподілі або звільненні пам'яті на купі, наприклад, семафорі або мютекс.