La lettura simultanea del vettore stl è sicura per thread?

Sto lavorando a un’applicazione in cui è previsto un numero enorme di thread per iterare su un insieme di valori stringa e cercare di associare i propri dati con quelli disponibili nell’elenco.

Sto cercando il seguente caso d’uso:

  1. Il vettore viene inizializzato con pochi elementi di tipo std :: string. (Diciamo che il nome dell’object è strList). strList verrà inizializzato al momento dell’avvio dell’applicazione.
  2. Tutti i thread eseguiranno iterazioni su strList per vedere se il valore corrisponde a almeno un elemento di strList.
  3. Nessun thread tenterà mai di modificare strList e sarà strettamente usato come object readonly.

Quindi potresti dirmi se le letture concorrenti sono thread-safe su oggetti vettoriali. Sto usando RHEL 6 e la versione di gcc è 4.5.x

per lo scenario che hai citato, è perfettamente sicuro.


In realtà, STL non è un modo corretto di riferirlo.
È la libreria standard C ++ .

Lo standard C ++ 03 non parla affatto di concorrenza, quindi l’aspetto della concorrenza è lasciato fuori come un dettaglio di implementazione per i compilatori. Quindi la documentazione fornita con il compilatore è dove si dovrebbe cercare risposte relative alla concorrenza.

La maggior parte delle implementazioni STL non sono thread-safe in quanto tali.
Ma per letture contemporanee dello stesso object da più thread la maggior parte delle implementazioni di STL sono effettivamente thread-safe.

Riferimenti:

MSDN dice:

Un singolo object è thread-safe per la lettura da più thread. Ad esempio, dato un object A, è sicuro leggere A dal thread 1 e dal thread 2 contemporaneamente.

La documentazione STL di Dinkumware dice:

Più thread possono leggere tranquillamente lo stesso object contenitore. (Esistono sottooggetti mutevoli non protetti all’interno di un object contenitore).

La documentazione GCC dice:

Attualmente utilizziamo la definizione SGI STL di sicurezza del thread, che afferma:

L’implementazione SGI di STL è thread-safe solo nel senso che gli accessi simultanei a contenitori distinti sono sicuri e gli accessi in lettura simultanei ai contenitori condivisi sono sicuri. Se più thread accedono a un singolo contenitore e potenzialmente almeno un thread potrebbe scrivere, l’utente è responsabile di garantire l’esclusione reciproca tra i thread durante gli accessi del contenitore.

Quindi, da quanto sopra, Sì, è sicuro thread in GCC per avere letture simultanee dello stesso object da più thread.

Nota: la libreria standard di GCC è un derivato del codice STL di SGI.

Per questo c’è una menzione specifica nel FDIS C ++ 0x (n3290).

§ 17.6.5.9 Evasione della corsa dati

L’intero paragrafo è di interesse ma più in particolare:

La funzione di libreria standard 3 / A C ++ non modifica direttamente o indirettamente oggetti (1.10) accessibili da thread diversi dal thread corrente a meno che gli oggetti non siano accessibili direttamente o indirettamente tramite gli argomenti non-const della funzione, incluso questo.

significa che puoi chiamare cbegin e cend su std::vector modo sicuro. Oltre a chiamare l’ operator== o l’ operator< su std::string .

6 / Le operazioni sugli iteratori ottenuti chiamando un contenitore di libreria standard o una funzione membro della stringa possono accedere al contenitore sottostante, ma non devono modificarlo.

significa che la semplice iterazione su un contenitore non dovrebbe modificare in alcun modo detto contenitore.

Nonostante 3 / sebbene, sembra che ci sia spazio per gli oggetti globali, come gli iteratori che modificano una sorta di object registro condiviso in cui si assocerebbero al contenitore (funzionalità di debug STL). Non ho senso di:

7 / Le implementazioni possono condividere i propri oggetti interni tra i thread se gli oggetti non sono visibili agli utenti e sono protetti contro le corse di dati.

altrimenti.

In ogni caso, lo Standard garantisce che l'iterazione sul vector sarà sicura ... ma non fornisce alcuna garanzia quando si tratta di leggere effettivamente gli oggetti (quelli sono i tuoi). In questo caso, questo è coperto perché std::string è coperto sopra.

EDIT: Come ha giustamente notato David Hammen, questo standard non è ancora pienamente implementato. Molti compilatori hanno già fornito le garanzie di cui sopra, anche se il precedente Standard non parlava mai dei thread. MSVC, gcc, clang, icc, comeau, ecc ... Tutti i grandi nomi dovrebbero già fornire questa garanzia, come si può vedere dalla risposta di Als.

In aggiunta alle regole generiche sull’elusione della corsa dei dati, in [container.requirements.dataraces] lo standard dice

-1- Al fine di evitare le razze di dati (17.6.5.9), le implementazioni devono considerare le seguenti funzioni come const : begin , end , rbegin , rend , front , back , data , find , lower_bound , upper_bound , equal_range , at e, tranne in contenitori associativi associativi o non ordinati, operator[] .

Quindi, anche se chiami non-const begin() / end() ecc. Finché non modifichi effettivamente nulla è sicuro.