Avoidance of Heap Contention
По умолчанию диспетчер строки, предоставляемые MFC и библиотеки ATL простые программы-оболочки поверх глобальной куче. Эта глобальной куче полностью потокобезопасной, означать, что несколько потоков могут выбирать и освобождать память из нее одновременно, не повредить кучу. Чтобы обеспечить потокобезопасность, куча должна выполнить сериализацию к самому себе. Обычно это выполняется с критической секцией или аналогично блокируя механизмом. При попытке доступа к куче 2 потока одновременно, один поток блокироваться до тех пор, пока запрос другого потока. Для многих приложений эта ситуация возникает редко, и влияние на производительность механизма кучи блокируя на производительность незначительно. Однако для приложений, которые часто обращаются к куче из конфликтов нескольких потоков для блокировки кучи может привести к приложению выполняться медленнее, чем если она была продета потоками (даже на компьютерах с несколькими ЦП).
Приложения, использующие CStringT особенно впечатлительный для навалить конфликт, так как операции в объектах CStringT часто необходима перераспределения буфера строки.
Один из способов решить конфликты кучи между потоками иметь каждый поток выборки строк из строки поток- локальной куче. Если строки, выбранные с помощью механизма распределения указанного потока используются только в этом потоке, выделения не должны быть потокобезопасным.
Пример
В приведенном ниже примере демонстрируются процедуры потока, которая выделяет собственную non-поток- защищенной частной кучи для использования строк в этом потоке.
DWORD WINAPI WorkerThreadProc(void* pBase)
{
// Declare a non-thread-safe heap just for this thread:
CWin32Heap stringHeap(HEAP_NO_SERIALIZE, 0, 0);
// Declare a string manager that uses the thread's heap:
CAtlStringMgr stringMgr(&stringHeap);
int nBase = *((int*)pBase);
int n = 1;
for(int nPower = 0; nPower < 10; nPower++)
{
// Use the thread's string manager, instead of the default:
CString strPower(&stringMgr);
strPower.Format(_T("%d"), n);
_tprintf_s(_T("%s\n"), strPower);
n *= nBase;
}
return(0);
}
Комментарии
Несколько потоков могут выполняться с помощью этой ту же процедуру потока, но поскольку каждый поток имеет собственную кучу отсутствие конфликтов между потоками. Кроме того, тот факт, что каждая куча не дает выигрыш в производительности потокобезопасной, измеряемое даже если только одна копия потока. Это результат кучи не с помощью ресурсоемкие операции блокирования, который необходимо защититься от параллельного доступа.
Для более осложненной процедуры потока, может быть удобно хранить указатель на него строки потока, в ячейке локального хранилища потока (TLS). Это позволяет другие функции, вызываемые процедурой потока для доступа к диспетчеру строки потока.