避免堆積競爭
MFC 和 ATL 所提供的預設字串管理員是全域堆積頂端的簡單包裝函式。 這個全域堆積完全安全線程,這表示多個線程可以同時配置和釋放記憶體,而不會損毀堆積。 為了協助提供線程安全性,堆積必須串行化本身的存取權。 這通常是使用重要區段或類似的鎖定機制來完成。 每當兩個線程嘗試同時存取堆積時,就會封鎖一個線程,直到另一個線程的要求完成為止。 對於許多應用程式而言,這種情況很少發生,而且堆積鎖定機制的效能影響微不足道。 不過,對於經常從堆積鎖定的多個線程爭用存取堆積的應用程式,可能會導致應用程式執行速度比單個線程更慢(即使是在具有多個 CPU 的計算機上)。
使用 CStringT 的應用程式特別容易發生堆積爭用,因為物件上的 CStringT
作業通常需要重新配置字串緩衝區。
緩和線程之間堆積爭用的其中一種方法是讓每個線程從私人線程本機堆積配置字串。 只要配置給特定線程的配置器所配置的字串只會在該線程中使用,配置器就不需要安全線程。
範例
下列範例說明線程程式,其會配置自己的私人非線程安全堆積,以用於該線程上的字串:
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) 位置可能很方便。 這可讓線程程式呼叫的其他函式存取線程的字串管理員。