Boost shared_ptr thread safe?

Ho una domanda su boost::shared_ptr .

Ci sono molte discussioni.

 using namespace boost; class CResource { // xxxxxx } class CResourceBase { public: void SetResource(shared_ptr res) { m_Res = res; } shared_ptr GetResource() { return m_Res; } private: shared_ptr m_Res; } CResourceBase base; //---------------------------------------------- // Thread_A: while (true) { //... shared_ptr nowResource = base.GetResource(); nowResource.doSomeThing(); //... } // Thread_B: shared_ptr nowResource; base.SetResource(nowResource); //... 

Q1

Se Thread_A non interessa il nowResource è il più recente, questa parte del codice avrà problemi?

Voglio dire quando Thread_B non è SetResource() completamente, Thread_A ottiene un punto smart errato da GetResource() ?

Q2

Cosa significa thread-safe?

Se non mi interessa sapere se la risorsa è la più recente, la funzione shared_ptr nowResource il programma quando viene rilasciata nowResource o il problema verrà shared_ptr ?

Dalla documentazione di boost:

shared_ptr oggetti shared_ptr offrono lo stesso livello di sicurezza dei thread dei tipi built-in. Un’istanza shared_ptr può essere “letta” (accessibile tramite le sole operazioni const) contemporaneamente da più thread. Diverse istanze di shared_ptr possono essere “scritte su” (a cui si accede usando operazioni mutabili come operator= o reset) simultaneamente da più thread (anche quando queste istanze sono copie e condividono lo stesso conteggio di riferimento al di sotto).

Qualsiasi altro accesso simultaneo provoca un comportamento indefinito.

Quindi il tuo utilizzo non è sicuro, poiché utilizza la lettura e la scrittura simultanee di m_res . Anche l’esempio 3 nella documentazione di boost lo illustra.

È necessario utilizzare un mutex separato che m_res l’accesso a m_res in SetResource / GetResource .

boost::shared_ptr<> offre un certo livello di sicurezza del thread. Il conteggio dei riferimenti viene manipolato in modo thread-safe (a meno che non si configuri boost per disabilitare il supporto per il threading).

Quindi puoi copiare un shared_ptr e il ref_count viene mantenuto correttamente. Quello che non si può fare in modo sicuro in più thread è modificare l’istanza dell’object shared_ptr effettiva da più thread (come ad esempio chiamando reset() su di esso da più thread). Quindi il tuo utilizzo non è sicuro: stai modificando l’istanza shared_ptr effettiva in più thread: dovrai avere la tua protezione.

Nel mio codice, shared_ptr ‘s sono in genere locals o parametri passati per valore, quindi non ci sono problemi. Usandoli da un thread all’altro generalmente uso una coda thread-safe.

Ovviamente niente di tutto questo riguarda la sicurezza del thread di accesso all’object puntato da shared_ptrshared_ptr anche da te.

Bene, la documentazione di tr1 :: shared_ptr (che si basa sul boost) racconta una storia diversa, il che implica che la gestione delle risorse è thread-safe, mentre l’accesso alla risorsa non lo è.

” …

Filo di sicurezza

Le caratteristiche di C ++ 0x sono: rvalue-ref / move support, allocator support, aliasing constructor, make_shared e allocate_shared. Inoltre, i costruttori che utilizzano i parametri auto_ptr sono deprecati in modalità C ++ 0x.

La sezione Sicurezza filo della documentazione di Boost shared_ptr dice che “gli oggetti shared_ptr offrono lo stesso livello di sicurezza dei thread dei tipi incorporati”. L’implementazione deve garantire che gli aggiornamenti simultanei per separare istanze shared_ptr siano corretti anche quando tali istanze condividono un conteggio di riferimento es

shared_ptr a (nuova A); shared_ptr b (a);

// Thread 1 // Thread 2

sono impostati(); b.reset ();

L’object ad allocazione dynamic deve essere distrutto esattamente da uno dei thread. I riferimenti deboli rendono le cose ancora più interessanti. Lo stato condiviso utilizzato per implementare shared_ptr deve essere trasparente per l’utente e gli invarianti devono essere conservati in ogni momento. I pezzi chiave dello stato condiviso sono i conteggi di riferimento forti e deboli. Gli aggiornamenti a questi devono essere atomici e visibili a tutti i thread per assicurare la corretta pulizia della risorsa gestita (che è, dopotutto, il lavoro di shared_ptr!) Su sistemi multiprocessore può essere necessaria la sincronizzazione della memoria in modo che gli aggiornamenti dei conteggi di riferimento e la distruzione della risorsa gestita sono senza razza.

…”

vedi http://gcc.gnu.org/onlinedocs/libstdc++/manual/memory.html#std.util.memory.shared_ptr

m_Res non è thread- safe, perché in lettura / scrittura simultanea, hai bisogno di boost :: atomic_store / load per proteggerlo.

 //--- Example 3 --- // thread A p = p3; // reads p3, writes p // thread B p3.reset(); // writes p3; undefined, simultaneous read/write 

Aggiungi, la tua class ha una condizione di riferimenti ciclici; the shared_ptr m_Res non può essere un membro di CResourceBase . Puoi invece usare weak_ptr .