2015-12-20 12 views
5

Così ho preso una classe OS lo scorso semestre e abbiamo avuto un progetto di concorrenza/threading. Era un sim dell'aeroporto che atterrò degli aerei/li fece decollare nella direzione che soffiava il vento. Dovevamo farlo in Java. Così ora che le finali sono finite e sono annoiato, sto provando a farlo in C++ 11. In Java ho usato una variabile sincronizzata per il wind (0 - 360) in main e l'ho passata ai 3 thread che stavo usando. La mia domanda è: puoi farlo in C++ 11? È un lettore/scrittore di base, un thread scrive/aggiorna il vento, l'altro 2 (decollo/terra) letto.Variabili condivise in C++ 11

Ho funzionato avendo una variabile del vento globale nel mio file di implementazione "threads.cpp". Ma c'è un modo per passare una variabile a tutti i thread che voglio e tutti li tengono d'occhio? O è meglio per me usare semplicemente la variabile globale e non passare nulla? (Perché/perché no?) Stavo guardando std::ref() ma non ha funzionato.

MODIFICA: Sto già utilizzando mutex e lock_guard. Sto solo cercando di capire come passare e mantenere una variabile aggiornata in tutti i thread. In questo momento si aggiorna solo nel thread di scrittura.

risposta

5

È possibile utilizzare un std::mutex con std::lock_guard per sincronizzare l'accesso ai dati condivisi. O se i dati condivisi rientrano in un numero intero, è possibile utilizzare std::atomic<int> senza bloccare.

Se si desidera evitare le variabili globali, passare semplicemente l'indirizzo dello stato condiviso alle funzioni del thread al momento dell'avvio. Per esempio:

void thread_entry1(std::atomic<int>* val) {} 
void thread_entry2(std::atomic<int>* val) {} 

std::atomic<int> shared_value; 
std::thread t1(thread_entry1, &shared_value); 
std::thread t2(thread_entry2, &shared_value); 
+0

Sì, questo è esattamente quello che stavo cercando di fare! Sembra quasi che si tratti più di un dolore, ma di usare solo la variante globale. C'è qualche +/- per farlo in questo modo? – lciamp

+3

Bene, la maggior parte delle persone considera le variabili globali come pratiche scadenti per la maggior parte del tempo. Rende il test più difficile, almeno. –

1

Si potrebbe voler creare per esempio, l'oggetto del vento, sul mucchio con new attraverso un std::shared_ptr. Passa questo puntatore a tutti i thread interessati e usa uno std::mutex e std::lock_guard per cambiarlo.

+0

Grazie. Devo dare un'occhiata a shared_ptr.Sto solo facendo il cambio da C++ 98 a 11, dovrebbe essere una divertente pausa invernale! – lciamp

+1

Stai anche facendo il passaggio da Java a C++ e questo è un punto cardine che devi capire. Negli oggetti Java vengono automaticamente creati nell'heap e nella memoria gestita per te. In C++ devi assumerti questa responsabilità da solo. Ma ci sono alcuni ottimi aiutanti per le librerie standard di C++ 11 (e C++ 14!) Di cui avete bisogno per rendere questo viaggio il più dolce possibile ... Benvenuti in C++ land, una grande pausa invernale! :)) –

2

L'utilizzo di std::mutex e std::lock_guard simula ciò che fa una variabile sincronizzata Java (solo in Java ciò avviene in segreto senza che tu lo sappia, in C++ lo fai esplicitamente).

Tuttavia, avendo un produttore (c'è solo una direzione di vento) e comunque solo i consumatori, è sufficiente scrivere in un esempio std::atomic<int> variabile con ordine rilassato, e da leggere da quella variabile da ciascun consumatore, sempre con un ordine rilassato. A meno che tu non abbia la necessità che la visione globale di tutti gli aeroplani sia coerente (ma poi dovresti eseguire una simulazione a serrature, che rende il threading senza senso), non c'è bisogno di sincronizzazione, devi solo assicurarti che ogni valore che le letture dell'aeroplano in qualsiasi momento sono corrette e non possono verificarsi risultati intermedi alterati. In altre parole, hai bisogno di un aggiornamento atomico.
L'ordine di memoria rilassato è sufficiente, poiché se tutto ciò che leggi è un valore, non è necessario che avvenga prima delle garanzie.

Un aggiornamento atomico (o meglio, una scrittura atomica) è almeno un ordine di grandezza, se non di più, più veloce. Le letture e le scritture atomiche con ordinamento rilassato sono in effetti semplici normali letture e scritture su molte (la maggior parte) architetture mainstream.

La variabile non deve essere globale, puoi anche tenerla nell'oscilloscopio del ciclo di simultion del thread principale e passare un riferimento (o un puntatore) ai thread.

+0

eh. Sembra atomico più appropriato per il mio problema rispetto a mutex/lock_guard. Quello che stavo facendo, perché stavo guardando il codice Java che ho già scritto, stava passando per valore invece che per riferimento. Dovrei prob usa atomico per il vento e mutex/lock_guard per le piste. Grazie per l'aiuto! – lciamp

+0

Il mutex per la pista ha sicuramente senso dal momento che solo un aereo può essere su una pista alla volta (senza cose che diventano cattive). Solo per il campionamento della direzione del vento attuale non è necessario il mutex. – Damon

+0

L'utilizzo di std :: atomic funziona sicuramente, ma si tratta di un'ottimizzazione prematura. Poiché ci sono più variabili (pista, vento, ...) un mutex per proteggere l'intero stato è la prima cosa da avere in mente. – galinette

Problemi correlati