C# multi-threading: Acquisire blocco di lettura necessarie?

È necessario acquisire un lock su una variabile prima di leggere da più thread?

  • Si potrebbe ottenere le risposte alle vostre multi-threading domande da leggere questo articolo. C’è anche una versione PDF scaricabile su quella pagina.
  • L’ampia gamma di risposte a questa domanda mostra c’è sicuramente la necessità per esso.
  • Si può fornire un esempio specifico? Ci sono un sacco di problemi in tutto questo… Altrimenti, “dipende” è la risposta corretta.
  • Grazie a tutti per i commenti. @Andy S: Nessun caso specifico. Chiedevo solo che l’approccio corretto è in varie situazioni. Martinho ha dato la risposta che cercavo.

 

12 Replies
  1. 90

    La risposta breve è: dipende.

    La risposta lunga è:

    • Se non è un valore condiviso, io.e, solo thread può vedere (o usato), non hai bisogno di alcuna sincronizzazione.

    • Se questo valore non è modificabile, cioè, è possibile impostare solo una volta e poi sempre e solo di leggere, è sicuro di farlo senza sincronizzazione (come non iniziare a leggere prima di scrivere completa).

    • Se è un “primitivo” tipo di un massimo di 32-bit (ad esempio byte, short, int) è possibile ottenere raffermo (vecchio) dati durante la lettura. Se non ti da fastidio, si sta insieme. Se i dati non aggiornati è indesiderabile, fare la variabile volatile possibile risolvere questo problema senza ulteriori sincronizzazione per legge. Ma se avete racing scrittori, è necessario seguire lo stesso consiglio per longsotto.

    • Se si tratta di un “primitivi”, tipo più di 32-bit (ad esempio long, decimal, double) avete bisogno di sincronizzazione, altrimenti si potrebbe leggere “la metà” di un valore, “la metà” di un altro, e ottenere pazzo risultati. Per questo l’approccio consigliato è quello di utilizzare i metodi di Intrecciate classe, sia per legge e scrive..

    • Se si tratta di un tipo di riferimento, è necessario di sincronizzazione per evitare di vedere uno stato non valido (Jeff Agnello immagine di esempio è una buona). Il blocco istruzione potrebbe essere sufficiente per che. Di nuovo, è necessario bloccare per lettura e scrittura.

    Ci sono alcuni altri punti da prendere in considerazione (per quanto tempo blocco, per esempio), ma credo che questi siano sufficienti per rispondere alla tua domanda.

    • Molto approfondita. Grazie per la tua risposta!
    • +1 questa è una grande risposta.
    • Si può ancora ottenere la “metà” di un valore, “la metà” di un altro per lunghi sulle applicazioni in esecuzione in modalità 64bit?
    • Cosa @Joe chiesto. Specialmente perché i “puntatori” per un tipo di riferimento sarebbe 64bit dimensioni e potrebbe, per esempio, essere controllati null da più thread contemporaneamente (verificare se il 64bit valore del puntatore è 0 internamente?), Mi piacerebbe pensare che non importa su le piattaforme a 64bit, ma mi piacerebbe conoscere l’effettiva risposta pure.
    • In base alla risposta (stackoverflow.com/a/154803/417939), volatile, funziona solo se si dispone di scrittori che non leggono mai, e i lettori che non scrivere mai
  2. 11

    Dipende dal tipo di variabile e la vostra piattaforma. Per esempio, la lettura Int64s non è garantito per essere atomica su macchine a 32 bit. Quindi, Intrecciata.Leggi.

    • +1 per indicare il “problema” (se avessi eventuali voti di sinistra…)
    • i voti sono di nuovo ora. +1 per il real
  3. 5

    Inoltre per le risposte qui sotto, si può anche fare un blocco di lettura utilizzando il ReadWriterLockSlim.

    Che consentono di fare solo un blocco di lettura durante la lettura e la scrittura di blocco quando si modifica la variabile. Più thread possono avere un blocco di lettura, allo stesso tempo, ma appena un filo richieste di un blocco di scrittura per tutti i nuovi richiesta sono bloccati fino a quando non è completato.

    Questo tipo di blocco sarebbe utile se si sta facendo un sacco di legge e non scrive.

    Come con la maggior parte dei problemi di multithreading, la ricerca è sufficiente per capire se si adatta veramente il vostro problema il ReadWriterLock non sarebbe adatto per ogni situazione di chiusura.

  4. 5

    Se il caricamento del valore è effettuato in 1 istruzioni di montaggio, non è necessario per ottenere un blocco. Non importa se il valore è cambiato da 10 minuti o 1 microsecondo fa. Volete solo il valore di ora.

    Tuttavia, se si sta caricando un ENORME array o una foto o qualcosa del genere, si sarebbe probabilmente una buona idea per bloccarlo. In teoria, si può ottenere interrotto durante il caricamento dei dati e sono la metà del primo elemento e la metà del secondo elemento.

    Se è una semplice variabile, anche se, come un bool int, non è necessario.

    • Attenzione a cosa si intende per variabile semplice! longs, doubles e decimals può richiedere più di un’istruzione di lettura a seconda dell’architettura sottostante.
    • Ok. Se la variabile è minore di architettura di dimensioni, è una instrution. “bool” e “int” sempre adattarsi a questo disegno di legge.
    • Esatto, stavo solo chiarendo che “semplice” variabile qui non significa “primitivo”-ish tipo.
  5. 3

    Dipende se o non è un locale o variabile condivisa, e se qualcosa può scrivere, nel frattempo, e che cosa hai intenzione di fare dopo la lettura.

    Se si effettua una decisione basata sulla variabile, in considerazione che la successiva riga di codice può essere basata su dati che è ora di stantio.

  6. 3

    Lettura non richiede un blocco, come lungo come lei non si cura circa la “correttezza” della lettura. È pericoloso solo se si tenta di scrivere senza una serratura.

    • L’originale della domanda chiedeva se un blocco è necessario per la lettura; non di chiusura. La lettura non richiede un blocco, fintanto che non si cura circa la “correttezza” delle leggi; così la prefazione del generale.
    • Si potrebbe aggiungere che il bit sulla correttezza di lettura per la risposta, e quindi rimuovere il generale e la vaghezza porta.
    • Fernandes – fatto.
    • Che rende il mio commento, ormai obsoleta, così l’ho tolto e con voto positivo.
  7. 2

    Se è una costante, n.

    Se è un aggiornabile valore, sì, se hai bisogno di coerenza.

    Per aggiornabili valori in cui il valore esatto deve essere gestita, allora sì, si dovrebbe utilizzare un blocco o un altro metodo di sincronizzazione per legge e scrive; e, forse, blocco durante l’intero ambito in cui viene utilizzato il valore.

  8. 2

    Risposta è dipende. Se il valore della variabile non cambia, quando i fili sono di accedere alla variabile. in caso contrario, è necessario.

    Inoltre, È possibile utilizzare Intrecciata.Serie XXX per il mantenimento di atomicità in lettura\scrittura della variabile .

  9. 1

    Necessario? N.

    …ma se è possibile, che un altro thread potrebbe provare a scrivere durante la lettura (come una raccolta, etc.) quindi potrebbe essere una buona idea.

  10. 1

    È 100% necessario a meno che non si è sicuri al 100% che il valore della variabile non cambia, mentre il lettore thread sono in esecuzione.

  11. 0

    Fintanto che non cambia durante gli altri thread di esecuzione non è necessario bloccarlo.
    Se il cambiamento, si dovrebbe utilizzare.

  12. 0

    Se la variabile è mai scritti da qualcuno (almeno al momento non è accessibile), non c’è bisogno di bloccarlo, perché non ci sono possibilità per i mancati aggiornamenti. Lo stesso vale se non ti importa di perdere gli aggiornamenti (il che significa che non è un problema se si ottiene un vecchio valore). Altrimenti si dovrebbe usare una sorta di sincronizzazione

    • Anche se non si cura gli aggiornamenti mancanti, è possibile ottenere valori non validi, se si scrive solo una parte di un oggetto prima di un lettore di passaggi…

Lascia un commento