Prevenzione dei conflitti dell'Heap

I gestori di stringhe predefiniti forniti da MFC e ATL sono wrapper semplici sopra un heap globale. Questo heap globale è completamente thread-safe, ovvero più thread possono allocare e liberare memoria contemporaneamente senza danneggiare l'heap. Per garantire la thread safety, l'heap deve serializzare l'accesso a se stesso. Questa operazione viene in genere eseguita con una sezione critica o un meccanismo di blocco simile. Ogni volta che due thread tentano di accedere contemporaneamente all'heap, un thread viene bloccato fino al termine della richiesta dell'altro thread. Per molte applicazioni, questa situazione si verifica raramente e l'impatto sulle prestazioni del meccanismo di blocco dell'heap è trascurabile. Tuttavia, per le applicazioni che accedono frequentemente all'heap da più thread contese per il blocco dell'heap possono rallentare l'esecuzione dell'applicazione rispetto a se fosse a thread singolo (anche nei computer con più CPU).

Le applicazioni che usano CStringT sono particolarmente soggette alla contesa dell'heap perché le operazioni sugli CStringT oggetti richiedono spesso la riallocazione del buffer di stringa.

Un modo per alleviare la contesa dell'heap tra thread consiste nell'avere ogni thread allocato stringhe da un heap locale di thread privato. Purché le stringhe allocate con un allocatore di un thread specifico vengano usate solo in tale thread, l'allocatore non deve essere thread-safe.

Esempio

L'esempio seguente illustra una routine thread che alloca il proprio heap privato non thread-safe da usare per le stringhe in tale thread:

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);
}

Commenti

È possibile che più thread vengano eseguiti usando questa stessa procedura di thread, ma poiché ogni thread ha un proprio heap non esiste alcuna contesa tra thread. Inoltre, il fatto che ogni heap non sia thread-safe offre un aumento misurabile delle prestazioni anche se è in esecuzione una sola copia del thread. Questo è il risultato dell'heap che non usa operazioni interlock costose per proteggersi dall'accesso simultaneo.

Per una procedura di thread più complessa, può essere utile archiviare un puntatore al gestore di stringhe del thread in uno slot di archiviazione locale del thread (TLS). Ciò consente ad altre funzioni chiamate dalla routine thread di accedere al gestore di stringhe del thread.

Vedi anche

Gestione della memoria con CStringT