Quando utilizzare volatile con il multi threading?

Se ci sono due thread che accede a una variabile globale quindi molti tutorial dire rendere la variabile volatile per evitare che il compilatore di memorizzazione nella cache la variabile in un registro e quindi non ottenere aggiornato correttamente.
Tuttavia due thread sia l’accesso a una variabile condivisa è qualcosa che richiede la protezione tramite un mutex non è vero?
Ma in questo caso, tra il filo di chiusura e rilasciare il mutex il codice è in una sezione critica in cui solo un thread può accedere alla variabile, nel qual caso la variabile non ha bisogno di essere volatile?

Quindi che cosa è l’uso/scopo di volatile in un programma multi-threaded?

  • In alcuni casi, non si vuole/ha bisogno di protezione dal mutex.
  • A volte è bene avere una condizione di competizione, altre volte no. Come state usando questa variabile?
  • Un esempio di quando si è “fine” a una gara, per favore?
  • Qui va. Immaginate di avere un thread che è l’elaborazione di una serie di attività. Il thread di lavoro incrementa un contatore ogni volta che finisce un compito. Il thread principale legge periodicamente il contatore e gli aggiornamenti dell’utente con le notizie dei progressi. Fintanto che il contatore è allineato correttamente per evitare di strappare non c’è bisogno di sincronizzare l’accesso. Anche se c’è una gara, è benigna.
  • Sarebbe difficile valutare la sicurezza di un tale dispositivo, senza un esame completo del codice. Anche se un esame concluso che le scritture sono atomica (discutibile) e completamente scritta, tramite la cache (difficile da dire), vorrei comunque respingere questo come “codice non valido.” È safetey sarebbe estremamente tenue, e facilmente rotto di piccole modifiche al codice. Maintennance programmatori avrebbero potuto rompere questo dispositivo facilmente, e i problemi non possono comparire in fase di test.
  • L’hardware su cui viene eseguito questo codice garantisce che il allineati variabili non soffrono di tearing. Se il lavoratore è in aggiornamento n a n+1, come la lettura, il lettore non importa se essi ottenere n o n+1. Importanti le decisioni saranno prese in quanto viene utilizzata solo per i report di stato.
  • Credo di non so che cosa intendi per “strappo.”
  • re strappo, io ti offro il seguente Joe Duffy: msdn.microsoft.com/en-us/magazine/cc817398.aspx
  • Wow, un muro di testo. 🙂 Ma grazie, non ho letto ancora. Io, quando ho la possibilità.
  • È tutta ottima roba, ma il bit di strappo è solo un paio di paragrafi.
  • Ottenere +23 punteggio domanda, accettare -18 risposta. F**k logica.
  • isvolatileusefulwiththreads.com (anche @DavidHeffernan, software.intel.com/en-us/blogs/2013/01/06/… è necessario leggere il pezzo su “benigna” gare di dati)
  • Quando usare: mai.
  • esempio di quando si è “fine” a una gara” ogni volta che è bello usare un mutex. O atomico. Praticamente tutti non banale MT programmi innocui condizioni di gara.

InformationsquelleAutor David Preston | 2010-12-29



4 Replies
  1. 153

    Breve & risposta rapida: volatile è (quasi) inutile indipendente dalla piattaforma, applicazione con multithreading programmazione. Essa non fornisce alcuna sincronizzazione, non crea memoria recinzioni, né garantire l’ordine di esecuzione delle operazioni. Non effettuare operazioni atomiche. Non ha il codice magicamente thread-safe. volatile può essere il singolo più frainteso impianto in tutte del C++. Vedere questo, questo e questo per ulteriori informazioni su volatile

    D’altra parte, volatile ha alcuni usi che potrebbero non essere così evidente. Può essere utilizzato nello stesso modo in cui si potrebbe utilizzare const per aiutare il compilatore mostrare dove si potrebbe fare un errore nell’accedere alle risorse condivise in una non protetta modo. Questo uso è discusso da Alexandrescu in questo articolo. Tuttavia, questo è fondamentalmente utilizzando il C++ tipo di sistema in un modo che è spesso visto come un espediente e può evocare un Comportamento Indefinito.

    volatile specificamente è stato destinato per essere usato quando si interfaccia con mappati in memoria hardware, gestori di segnale e il setjmp codice macchina dell’istruzione. Questo rende volatile direttamente applicabili ai sistemi di programmazione di livello piuttosto che il normale applicazioni a livello di programmazione.

    2003 C++ Standard non dire che volatile si applica a qualsiasi tipo di Acquisire o di Rilascio semantica variabili. Infatti, la Norma è completamente in silenzio su tutte le questioni di multithreading. Tuttavia, piattaforme specifiche si applicano Acquisire e Rilasciare semantica volatile variabili.

    [Aggiornamento per C++11]

    Standard C++11 ora non riconoscere il multithreading direttamente nel modello di memoria e la lingua, e fornisce servizi bibliotecari per affrontare con una piattaforma indipendente dalla strada. Tuttavia la semantica di volatile ancora non sono cambiate. volatile non è ancora un meccanismo di sincronizzazione. Bjarne Stroustrup dice nel TCPPPL4E:

    Non utilizzare volatile tranne nel codice di basso livello che si occupa direttamente
    con l’hardware.

    Non assumere volatile ha un significato speciale nel modello di memoria. Si
    non. Non è-come in alcuni dei più recenti linguaggi-un
    meccanismo di sincronizzazione. Per ottenere la sincronizzazione, utilizzare atomic, un
    mutex, o un condition_variable.

    [/Aggiornamento di fine]

    Soprattutto si applica il C++ linguaggio stesso, come definito dal 2003 Standard (e ora il 2011 Standard). Alcune piattaforme specifiche tuttavia di aggiungere ulteriori funzionalità o restrizioni a ciò che volatile fa. Per esempio, in MSVC 2010 (almeno) di Acquisire e Rilasciare semantica fare si applica a determinate operazioni sul volatile variabili. Da MSDN:

    Durante l’ottimizzazione, il compilatore deve mantenere ordine tra i riferimenti
    per oggetti volatili come pure i riferimenti ad altri oggetti globali. In
    particolare,

    Una scrittura un volatile oggetto volatili (scrivere) ha Comunicato semantica; un
    riferimento a un oggetto globale o statico che si verifica prima di scrivere un
    volatile oggetto l’istruzione, la sequenza di verificarsi prima che
    volatile a scrivere in binario compilato.

    Una lettura di un volatile oggetto volatili (leggi) ha Acquisire semantica; un
    riferimento a un oggetto globale o statico che si verifica dopo una lettura di
    memoria volatile nelle istruzioni in sequenza si verifica dopo che
    volatile leggere il binario compilato.

    Tuttavia, si potrebbe prendere nota del fatto che, se segui il link di cui sopra, c’è un certo dibattito nei commenti dell’esistenza o meno di acquisire/semantica di rilascio effettivamente applicare in questo caso.

    • +1 ottimo link. La semantica di volatile non deve essere confuso tra le lingue, tra cui quello che potrebbe essere trovato in un dizionario 🙂 (porta molto rigide modello di memoria semantica di Java, per esempio, ma questo è un diverso linguaggio/ambiente).
    • Alcuni compilatori fornire ulteriori semantica di volatile che è utile per il multithreading di sviluppo, ma questo non è sicuramente parte dello standard.
    • Parte di me vuole downvote questo a causa del tono condiscendente della risposta e il primo commento. “volatile è inutile” è simile a “manuale di allocazione di memoria è inutile”. Se è possibile scrivere un programma multithread senza volatile è perché stava sulle spalle di persone che hanno usato volatile per implementare librerie di threading.
    • solo perché qualcosa sfide che le tue convinzioni non condiscendente
    • Penso che il primo commento affermando “se si downvote non capire” ha colpito la mia interpretazione del tono. Diverso da quello che ho letto come una dichiarazione forte contro l’uso di volatile che è probabilmente corretto, per la maggior parte delle persone la scrittura di codice a livello di applicazione.
    • no, leggi cosa volatile in realtà non in C++. Cosa @Giovanni detto è corretto, fine della storia. Non ha nulla a che fare con il codice dell’applicazione vs codice della libreria, o “ordinaria” vs “come dio onnisciente programmatori” per quella materia. volatile è inutile e inutile per la sincronizzazione tra i thread. Filettatura librerie non possono essere implementate in termini di volatile; deve basarsi sulle specifiche della piattaforma dettagli comunque, e quando si basano su quelle, non è più necessario volatile.
    • è superfluo e inutile per la sincronizzazione tra i thread” (che è quello che hai detto) non è la stessa cosa come “volatile è inutile per la programmazione multithread” (che è quello che Giovanni ha detto in risposta). Si è corretto al 100%, ma non sono d’accordo con Giovanni (parzialmente) – volatili può ancora essere utilizzato per la programmazione multithread (per un insieme molto limitato di compiti)
    • ad esempio, vedere il decimo risposta (da “Spud”) nei commenti qui per un uso legittimo di volatili: software.intel.com/en-us/blogs/2007/11/30/… (anche se questo È un po ‘ x86 specifici come altre piattaforme di maggio richiedono core per scaricare i dati con le une alle altre, volatile, ovviamente non fare)
    • Quindi hai praticamente detto “non è utile! …supponendo che questo, e tralasciando questo e quello, e…”. Tutto può essere vero se si fa abbastanza ipotesi; e hai sicuramente abbandonato il C++ come linguaggio con quelli.
    • beh, non ha detto che era inutile per tutto e non ho mai detto che non è detto che sia. Si dice ancora che la sua inutile per la programmazione multithread, che è quello che sto contestando. La sua non è particolarmente utile, ma non è del tutto inutile sia.
    • Tutto ciò che è utile è utile solo in un determinato insieme di requisiti o condizioni. Volatile è utile per la programmazione multithread sotto una rigida serie di condizioni (e, in alcuni casi, può essere anche meglio (per una definizione migliore) di alternative). Si dice “ignorando questo che e..” ma il caso quando il volatile è utile per il multithreading non trascurare nulla. Hai fatto qualcosa che non ho mai sostenuto. Sì, l’utilità di volatile è limitato, ma esiste – ma siamo tutti d’accordo che NON è utile per la sincronizzazione.
    • Il mio punto è che volatile è un linguaggio C++ concetto, non un’implementazione concetto. Ma hai detto che era utile a causa di alcuni dettagli di implementazione. Che non ha implicazioni sulla utilità in C++.
    • capito
    • Penso che si dovrebbe considerare l’aggiunta alla tua risposta, che volatile è release&acquisire [semantica Visual C++ ](msdn.microsoft.com/en-us/library/12a04hfd%28v=vs.80%29.aspx) (vedi anche la mia risposta qui: stackoverflow.com/questions/6995310/…)
    • Di recente ho fatto un’ampia elaborativi modifica di questa risposta. Ho incluso alcune specifiche per la piattaforma dettagli.
    • Faccio fatica a pensare ad un mondo reale, ad esempio, utilizzare volatili in normali applicazioni a livello di programmazione, c’è uno?
    • Che cosa è “Windows”del 2010?
    • Un errore di battitura.
    • Questo ha bisogno di un aggiornamento per parlare di std::atomic<T>
    • Jan 20 modifica incluso parlare di atomi e di altri dispositivi.
    • non usare volatili, tranne nel codice di basso livello che si occupa direttamente con l’hardware.” Fortemente in disaccordo. Volatile utile di gestori di segnale, per alcuni casi di codice multithread, per il test… È solo che non è una sostituzione per atomics nella maggior parte dei casi.
    • Unix self-tubo trucco è più utile per i gestori di segnali di volatili e in modo molto più robusto di codice.

  2. 30

    Volatile è di tanto in tanto utile per il seguente motivo: questo codice:

    /* global */ bool flag = false;
    
    while (!flag) {}

    è ottimizzato da gcc:

    if (!flag) { while (true) {} }

    Che ovviamente non è corretto, se la bandiera viene scritto da altri thread. Si noti che, senza questa ottimizzazione del meccanismo di sincronizzazione probabilmente funziona (a seconda del codice di alcune barriere di memoria può essere necessario) – non c’è bisogno di un mutex in 1 produttore – 1 consumatore scenario.

    Altrimenti la parola chiave volatile è troppo strano per essere utilizzabile – non fornire alcuna memoria garanzie di ordinazione wrt sia volatile e non accede e non fornisce alcun operazioni atomiche – ad esempio, puoi ottenere nessun aiuto da parte del compilatore con la parola chiave volatile, tranne disabili registro di memorizzazione nella cache.

    • Se non ricordo male, C++0x atomica, è destinata a fare bene ciò che un sacco di persone credono (erroneamente) è fatto da volatile.
    • Sì, sì, sì. E ‘ divertente, ho aggiunto una riga su C++0x atomica strutture, ma poi rimosso, poiché sembra non connessi con la domanda esatta : C++0x atomica è, come si deve, in calcestruzzo di load/store semantica, per ogni accesso sono molto utili.
    • volatile non impedisce gli accessi alla memoria dall’essere riordinati. volatile accessi non essere riordinati con rispetto gli uni con gli altri, ma che forniscono un non garanzia circa il riordino rispetto ai non-volatile oggetti, e così, sono sostanzialmente inutili come le bandiere come bene.
    • Penso che la maggior parte dei “volatili è inutile” folla fanno affidamento sul fatto che è più probabile che il codice come while (!global_flag) { sleep(1); } funzionerà senza volatile perché i loro compilatori non guardare in sleep() durante l’ottimizzazione, e quindi si presuppone che sleep() può modificare global_flag e quindi il diritto, il codice prodotto per le ragioni sbagliate. Forse un esempio giusto potrebbe essere costruito con LLVM link ottimizzazioni in fase di?
    • Ma il codice che utilizza occupato in attesa – come qualcosa da evitare.
    • Penso che hai capito a testa in giù. Il “volatile è inutile” folla si basa sul semplice fatto che volatile non protegge contro il riordino, il che significa che è del tutto inutile per la sincronizzazione. Altri approcci possono essere altrettanto inutile (come si parla, in fase di collegamento di ottimizzazione del codice, potrebbe consentire al compilatore di sbirciare nel codice si presuppone che il compilatore avrebbe trattato come una scatola nera), ma che non consente di risolvere le carenze di volatile.
    • alcuni usi di bandiere non richiedono che essi non sono riordinati (anche se la maggior parte, mentre non vi è un molto, molto di nicchia caso d’uso in cui volatile è perfettamente bene, ci sono un sacco di persone che abusano di volatili in strade poco sicure)
    • nome di una situazione in cui il riordino non è un problema. Il flag viene utilizzato per indicare che un certo evento si è verificato, e che funziona solo se l’evento è in realtà si è verificato quando il flag è impostato. Quali altri casi ti viene in mente?
    • Si veda l’articolo di Arco di Robinson (collegato altrove su questa pagina), 10 ° commento (da “Spud”). Fondamentalmente, il riordino non cambia la logica del codice. Il codice postato utilizza il flag per annullare un’operazione (piuttosto che di segnale il compito è fatto), in modo che non importa se l’attività viene annullata prima o dopo il codice (esempio: while (work_left) { do_piece_of_work(); if (cancel) break;}, se il comando è stato riordinato all’interno del ciclo, la logica è ancora valido. Ho avuto un pezzo di codice che ha lavorato allo stesso modo: se il thread principale vuole risolvere, si imposta il flag per altri thread, ma non…
    • …importa se gli altri thread fare un paio di iterazioni del loro lavoro loop prima di terminare, come lungo come accade ragionevolmente presto dopo che il flag è impostato. Naturalmente, questo è l’UNICO utilizzo che mi viene in mente e la sua piuttosto di nicchia (e potrebbe non funzionare su piattaforme dove la scrittura di un volatile variabile non fare il cambiamento più visibile agli altri thread, anche se, almeno su x86 e x86-64 funziona). Io di certo non lo consigliamo a nessuno di fare veramente che senza una buona ragione, sto solo dicendo che una dichiarazione coperta come “volatile non è MAI utile in codice multithread,” non è corretto al 100%.
    • Poiché ero alla ricerca di una buona risposta potrei link perché volatile è inutile, non posso lasciare questi commenti qui stand. Quello che Dan sta dicendo qui funziona solo per x86 a causa della sua forte sottostante modello di memoria. Ciò che egli propone qui è ugualmente rotto, come in ogni altro caso d’uso di volatili su molte altre piattaforme (ad esempio, non vi è alcuna garanzia che non leggi un valore non aggiornato dalla cache). Quindi sì, se si desidera un programma che non funziona solo in x86, volatile è davvero mai utile..
    • La mia sintesi di tutto questo è: (1.) esistono esempi in cui il volatile è corretto/utile per il multithreading (@Dan esempio: uso di un volatile bool per interrompere un thread loop. un altro esempio) (1.addendum) gli esempi in cui è volatile corretta/utile per il multithreading sono compilatore/implementazione dipendente (un compilatore può avere atomica comportamento per volatili, mentre un altro non si può) E che dipende dall’hardware (arm vs x86) (3.) la dichiarazione di “volatile non è MAI corretto/utile nel codice multithread,” è sbagliato, perché esistono almeno un esempio di contatore
    • Ci sono varie piattaforme dove è possibile economicamente garantire una scrittura, una scrittura volatile-una volta variabile infine, essere visto in tutti gli altri thread (in pochi secondi); infatti, ottimizzazione potrebbe essere aiutato se non ci fosse un qualificatore che erano più morbida rispetto volatile in modo che il compilatore dovrebbe essere libero di ottimizzare un delimitata numero di accessi consecutivi [ad esempio, se il compilatore si srotola un ciclo di 8 volte, avrebbe solo per controllare la variabile una volta srotolato il ciclo, piuttosto che il controllo di otto volte]. L’overhead imposto da un meccanismo sciolto con la semantica…
    • …potrebbe essere molto meno di quanto sarebbe necessario quando si utilizza un meccanismo con più rigida semantica.
    • che è esattamente quello che std::atomic fa con i modelli di memoria più debole di acquisizione/rilascio.
    • Così anche voi pensate che “il riferimento a uno dopo la fine di una matrice” non è sempre sbagliato, perché c’è un esempio in cui “funziona”? Non è così che c lavora e particolarmente pericolosa a pensare se la concorrenza è coinvolto.
    • se da “il riferimento a uno dopo la fine di una matrice” significapunto passato il fine di una matrice”, allora sei sciatta con la terminologia che non riferimento alla memoria punti.
    • Sono appena pignoleria o davvero confuso? Avrei pensato una qualsiasi programmatore C++ sa che la memoria di accesso al di fuori di un array è un comportamento indefinito, ma funziona ancora abbastanza spesso – che è il punto della discussione non c’. Ma sì ho perso la “memoria” non c’e no non parlavo di puntamento passato il fine di una matrice perché non è un comportamento indefinito.
    • No, io veramente non so se si intende che punta a quando si dice riferimenti – non mi considero di pignoleria a punto (sic!) quando questi due termini sono di uso improprio, dal momento che sono completamente diverse. Ora che si è chiarito che si tratta di un accesso alla memoria da riferimenti “un passato matrice fine” può apparentemente successo, ho perfettamente capito la tua affermazione.
    • Solo per chiarire il motivo per cui ho risposto, in primo luogo, hai scritto “avrei pensato una qualsiasi programmatore C++ sa che la memoria di accesso al di fuori di un array è un comportamento indefinito” ma io direi che la stragrande maggioranza degli sviluppatori C++ non sapere cosa UB mezzi e non conosci la differenza tra punto e riferimento. Che la maggioranza è come il nero materia e difficilmente essere trovato in MODO o conferenze o la lettura di C++ blog – sono ancora la maggioranza.

  3. -1

    Avete bisogno di volatili e, eventualmente, di chiusura.

    volatile racconta l’ottimizzatore che il valore può cambiare in modo asincrono, così

    volatile bool flag = false;
    
    while (!flag) {
        /*do something*/
    }

    sarà flag di lettura ogni volta tutto il ciclo.

    Se si attiva l’ottimizzazione off o rendere ogni variabile volatile di un programma si comporterà, ma più lento. volatile significa solo ‘so che si può avere solo di leggere e di sapere che cosa si dice, ma se dico di leggere e poi leggere.

    Di chiusura è una parte del programma. Così ,a proposito, se si implementa semafori poi tra le altre cose devono essere volatile. (Non provare, è difficile, sarà probabilmente bisogno di un po ‘ di assembler o il nuovo atomic stuff, ed è già stato fatto).

    • Ma non è questo, e lo stesso esempio nell’altra risposta, occupato in attesa, e quindi qualcosa che dovrebbe essere evitato? Se questo è un esempio volutamente semplice, ci sono esempi di vita reale che non sono inventate?
    • Ok sì. È davvero bisogno di fare qualcosa in parentesi graffe (devo modificare il post). Lunga attesa è di solito una cattiva idea. Potrebbe essere l’elaborazione di qualcosa (una lista) fino a quando un altro thread segnali di stop. Senza valatile continuerà per sempre, e per questo esempio, il blocco è necessario, bool è atomica.
    • Lunga attesa è di tanto in tanto una buona soluzione. In particolare, se si aspetta di avere solo aspettare un paio di cicli di clock, si porta molto meno overhead di molto più pesante approccio di sospendere il thread. Naturalmente, come ho già detto in altri commenti, esempi come questo sono errate in quanto essi assumono legge/scrive la bandiera non essere riordinati con il codice protegge, e non tale garanzia è data, e così, volatile non è molto utile anche in questo caso. Ma la lunga attesa è occasionalmente tecnica utile.
    • la mia comprensione delle cose è che la volatilità indica al compilatore che la variabile può essere letta/scritta in modo asincrono al programma (da un altro thread o il mio hardware) si dovrebbe dare la semantica del “se dico di leggere o scrivere e poi leggere o scrivere, e farlo quando lo dirò io.”. Se la CPU è di riordino di istruzione di modificare questi semantica, quindi il compilatore deve sconfiggere questa ottimizzazione pure. Mi manca qualcosa.
    • Sì e no. La prima metà è corretto. Ma questo significa solo che la CPU e il compilatore non sono autorizzati a riordinare le variabili volatile rispetto ad altri. Se io leggo un volatile variabile, e poi leggere un volatile variabile B, quindi il compilatore deve emettere il codice che è garantito (anche con CPU di riordino) per leggere prima di B., Ma non fornisce alcuna garanzia su tutti i non-volatile variabile accessi. Essi possono essere riordinate intorno al vostro volatile leggere/scrivere bene. Quindi a meno di non fare ogni variabile nel programma di volatili, non vi darà la garanzia ti interessa
    • Che non è vero. Non vi è alcun obbligo che volatile evitare CPU riordino e sulla maggior parte delle piattaforme moderne, in realtà non fanno così.
    • Ti basta andare in giro a postare cose false su volatile? Avete uno Standard differente rispetto a queste persone? stackoverflow.com/questions/2535148/…
    • Leggere i commenti e le due risposte che sembrano in disaccordo con me e vedrai che non è così. È non trovare accede a volatiles emettitori di barriere di memoria, in modo che il riordino è non ha impedito.
    • Intendiamo riordino delle letture/scritture in tale specifico volatile, che è garantito che non si verificano non di riordino delle eventuali detto di lettura/scrittura rispetto ad altre dichiarazioni (anche se non sono anche volatile), che si è permesso di accadere. È l’ultima cosa intendi?
    • Di nuovo, vedrete che praticamente su ogni compilatore, legge e scrive volatile le variabili di non emettono le barriere di memoria, anche su piattaforme che li richiedono, per evitare che legge e scrive da essere riordinati e/o integrata. Provare. (Siete d’accordo che la CPU può fondersi scrive ordinario di memoria? Vedi il compilatore di fare qualcosa per fermarlo quando due scrive si verificano allo stesso volatile? Che dire, scrive a due adiacenti volatile shorts, o un “ABA” scrivere a loro? Non si vede nulla emessa a smettere di scrivere combinazione?)
    • si accetta che la CPU può fondersi scrive ordinario di memoria?” Chi se ne frega?
    • Bene, perché se è in grado di fondersi due scrive, non può conservare l’ordine di loro. Il punto è che non c’è assolutamente nessuna restrizione sulla Cpu possibilità di riordinare, modificare, o unire le scrive. Nulla impone alcuna restrizione e attuale Cpu farlo.
    • Non dovrebbe il compilatore C, numero limite di istruzioni tra volatili di lettura/scrittura, per garantire che la volatilità sia onorato?, O ci sono Cpu che non consentono volatile per essere implementato?
    • Qual è la definizione di “fondersi due scrive”?
    • Il codice dice di fare due o tre scrive e la CPU invece fa uno o due. Per esempio, si fa i=1; j=2; k=3; e la CPU i=1; k=3; in una singola operazione atomica. Nulla impedisce che una CPU da questo fatto, anche se i, j, e k sono volatile e reale Cpu farlo. Le cpu sono in grado anche di ottimizzare out scrive volatiles e del mondo reale, Cpu effettivamente fare questo. Così i=1; j=2; i=3; può causare la i=1; scrivere sempre ottimizzato, ancora una volta, anche se i è volatile. Questo è il motivo per cui molte Cpu memoria barriera operazioni e volatile non li uso, né è necessario.
    • Infatti con tutte le variabili a partire da 0, se i=1; j=2; i=3; è trasformato in j=2; i=3; che si rompono un altro thread in attesa (erroneamente) che j==2 può accadere solo se i>0.

  4. -2
    #include <iostream>
    #include <thread>
    #include <unistd.h>
    using namespace std;
    
    bool checkValue = false;
    
    int main()
    {
        std::thread writer([&](){
                sleep(2);
                checkValue = true;
                std::cout << "Value of checkValue set to " << checkValue << std::endl;
            });
    
        std::thread reader([&](){
                while(!checkValue);
            });
    
        writer.join();
        reader.join();
    }

    Una volta che un intervistatore che credeva anche che la volatilità è inutile sostenuto con me che l’Ottimizzazione non causano alcun problema e stato in riferimento a diversi nuclei di aver separato linee di cache e tutto quello che (non ho mai capito bene che cosa era esattamente di riferimento per). Ma questo pezzo di codice quando viene compilato con -O3 g++ g++ -O3 thread.cpp -lpthread), mostra comportamenti indefiniti. In sostanza se il valore viene impostato prima dell’mentre il check funziona bene e se non va in un loop senza preoccuparsi di recuperare il valore (che in realtà era cambiato dall’altro thread). Fondamentalmente credo che il valore di checkValue ottiene solo una volta recuperata nel registro e non viene mai controllato di nuovo sotto il massimo livello di ottimizzazione. Se è impostato su true prima di fetch, funziona bene e se non va in un loop. Per favore mi corregga se sbaglio.

    • Che cosa ha a che fare con volatile? Sì, questo codice è UB-ma è UB con volatile così.

Lascia un commento