ReaderWriterLockSlim fornisce sicurezza di thread e velocità (rispetto a un blocco tradizionale) quando si utilizza un elenco?

2

Ho una lista, a cui scrivo una volta in ogni ciclo di aggiornamento e poi creo alcune attività che creano una lettura che elenca e crea una copia per manipolare quei dati. Più o meno è List.ToList() call per creare una nuova lista invece di usarla per riferimento. Ogni attività manipola i dati in se stessi e produce i risultati. Attualmente sto usando un blocco tradizionale sotto forma di

lock(LockObject){
//write stuff
}

durante la scrittura e

lock(LockObject){
localList=List.ToList();
}

durante la lettura.

L'utilizzo dell'oggetto ReaderWriterLockSlim invece del modo in cui lo sto facendo ora mi offre vantaggi in termini di velocità? Inoltre, il metodo ToList() è considerato una lettura in questo caso?

Modifica chiarificazione

  1. I lettori creano una copia perché manipolano i dati in modo diverso, ognuno di essi rimuove o aggiunge dati all'elenco su a modo loro. (alcuni potrebbero aggiungere dati precedenti di cui hanno ancora bisogno mentre altri rimuovono i dati di cui non hanno bisogno. Anche il ciclo di aggiornamento si verifica una volta ogni pochi secondi, quindi è comune.
  2. A volte, se l'immissione dei dati è molto veloce, potrebbe iniziare un ciclo di aggiornamento / scrittura prima che tutti i lettori abbiano completato l'elaborazione (ma se ottengono i dati aggiornati invece non è un problema per me).
  3. Fondamentalmente i lettori sono lì per presentare i dati correnti a altri. Quindi, se i dati vengono modificati prima ancora che inizino a presentarli va bene. Finché non provano a elaborare i dati mentre sono in fase di aggiornamento (che probabilmente genererebbe un'eccezione)
posta John Demetriou 25.08.2015 - 09:52
fonte

1 risposta

2

Dipende. L'utilizzo di un blocco lettore / scrittore anziché di una sezione critica può essere utile se le operazioni di lettura sono notevolmente più comuni delle operazioni di scrittura. Ma penso che potresti ottenere di più modificando la tua architettura di applicazione.

Se le scritture sono rare, è possibile ottenere prestazioni decisamente migliori trattando la raccolta come immutabile e producendo una lista completamente nuova quando cambia. Puoi quindi utilizzare Interlocked.CompareExchange per aggiornare il riferimento al elencare in un modo sicuro per i thread. Questo dovrebbe impedire ai lettori di dover fare una copia difensiva (che dovrebbe essere una grande vittoria se la lettura è più comune della scrittura) e rimuovere la necessità di bloccare.

In alternativa, se la scrittura è più comune della lettura, può valere la pena valutare un ConcurrentStack come sostituto dell'elenco. Questo fornisce un metodo ToArray atomico che può essere utilizzato per creare copie senza bisogno di blocchi. In alternativa, se l'ordine non è importante nel tuo elenco, una ConcurrentBag potrebbe avere un rendimento migliore.

Modifica dopo chiarificazione

Continuo a pensare che sarebbe meglio copiare l'elenco quando lo modifichi, in quanto ciò ti consente di eliminare completamente il blocco. Anche se i lettori devono modificare il contenuto della lista durante l'elaborazione, sarebbe meglio refactored per utilizzare uno stile di streaming, ad es. LINQ to Objects, in modo che queste operazioni non duplichino effettivamente i dati. Per ulteriori informazioni sulla conversione di codice esistente in questo stile, consulta Martin Fowler Refactoring con loop e raccolta pipeline .

In caso contrario, immagino che vedresti un piccolo guadagno che passa al blocco lettore / scrittore, ma a meno che la contesa del blocco sia insolitamente problematica per la tua applicazione dubito che sarà evidente.

    
risposta data 25.08.2015 - 10:14
fonte

Leggi altre domande sui tag