Di Windows Threads: quando si dovrebbe usare InterlockedExchangeAdd ()?
-
20-09-2019 - |
Domanda
La denominazione di questa funzione sembra che questo è un certo roba complicata in corso. Quando esattamente si fa a sapere che questa è la strada da percorrere invece di fare qualcosa di simile:
Preparazione CRITICAL_SECTION cs; int * p = malloc (sizeof (int)); // Assegnazione del sito InitializeCriticalSection (& cs); // SUGGERIMENTO per la prima scrittura
Thread # 1 { * P = 1; // Scrivi }
Thread # 2 { EnterCriticalSection (& cs); * P = 2; // seconda operazione di scrittura LeaveCriticalSection (& cs); }
Ho una scrittura che viene fatto in un thread:
Run()
{
// some code
m_bIsTerminated = TRUE;
// some more code
}
Poi, ho una lettura che viene fatto in un altro thread (potenzialmente allo stesso tempo):
Terminate()
{
// some code
if( m_bIsTerminated )
{
m_dwThreadId = 0;
m_hThread = NULL;
m_evExit.SetEvent();
return;
}
// even more code
}
Qual è la soluzione migliore per risolvere questa condizione di gara? Sono sezioni critiche la strada da percorrere o è l'uso di InterlockedExchangeAdd () più utile?
Soluzione
InterlockedExchangeAdd viene utilizzata per aggiungere un valore ad un intero come un'operazione atomica, il che significa che non sarà necessario utilizzare una sezione critica. Questo elimina anche il rischio di una situazione di stallo, se uno dei tuoi thread genera un'eccezione -. È necessario fare in modo che non si tiene alcun blocco di qualsiasi tipo come che impedirebbe altri thread di acquisire che il blocco
Per lo scenario si può sicuramente utilizzare una funzione Interlocked ...-, ma vorrei utilizzare un evento (CreateEvent, SetEvent, WaitForSingleObject), probabilmente perché mi ritrovo spesso a dover attendere per più di un oggetto (si può aspettare per zero secondi nello scenario).
UPD: Utilizzando volatile per la variabile può funzionare, tuttavia non è consigliabile, vedi: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2016.html e http://www-949.ibm. com / software / razionale / caffè / blog / CCPP-parallelo-multicore / tag / c% 2B% 2B0x per esempio.
Se si vuole essere portatile, un'occhiata a boost :: filo .
Altri suggerimenti
Nel tuo caso, non c'è alcuna condizione di competizione. La variabile non viene mai azzerato di nuovo a FALSE, è vero? E 'solo un interruttore "si prega di morire" per il filo, giusto? Quindi non c'è bisogno per la sincronizzazione di qualsiasi tipo.
La famiglia InterlockedXXX di funzioni fa uso di atomiche comandi a 3 operandi di Intel CPU (xadd e CMPXCNG). Quindi sono molto meno costosa di una sezione critica. E quello che si desidera per l'assegnazione thread-safe è InterlockedCompareExchange ().
UPD:. E il marchio la variabile come volatile
Assicurarsi m_bIsTerminated è contrassegnato come volatile, e si dovrebbe essere ok. Anche se sembra piuttosto strano per me che avresti // altro codice dopo aver impostato "è terminato" true. Che cosa fa esattamente quella variabile indica?
Il tuo "race condition" è che i vari elementi del // più codice in grado di eseguire in ordine diverso. La variabile non aiuta che. È il vostro obiettivo per ottenere loro di eseguire in un ordine deterministico? Se sì, avresti bisogno di un variabile di condizione di aspettare un thread e impostare in un altro. Se proprio non si vuole che l'esecuzione contemporaneamente, una sezione critica andrebbe bene.