2013-01-14 5 views
16

Sto usando lo ReaderWriterLockSlim per un po 'di tempo e ha soddisfatto le mie esigenze fino a questo punto. Mentre continuo a perfezionare la mia applicazione, trovo che ReaderWriterLockSlim è leggermente sub-ottimale per il mio caso d'uso.Esiste un equivalente ReaderWriterLockSlim che favorisce i lettori?

Per documentazione (e la mia esperienza), favorisce gli scrittori sui lettori (cioè quando i lettori e gli scrittori sono in coda, gli scrittori avranno la preferenza). Tuttavia, ho bisogno di un equivalente che favorisca i lettori. Capisco gli effetti collaterali di tale componente (in particolare, il problema di fame di scrittore).

Ci sono degli equivalenti pronti per la produzione a cui qualcuno può puntare? Grazie.

+3

L'assenza di codice non può mai essere dimostrata in modo definitivo. Ma no, è abbastanza improbabile. Si prega di evitare di fare domande per lo shopping. –

+0

Se si desidera favorire le letture, perché non si sostituisce semplicemente l'elenco interno con un clone aggiornato? Il tuo codice sarà bloccato ma un po 'più pesante sugli aggiornamenti. – jgauffin

+1

Sì, sembra che si possa risolvere questo problema con una copia come suggerisce jgauffin, o se la struttura dei dati è troppo grande per una copia economica, con un buffer di scrittura, quindi le scritture sono meno frequenti. Quindi si potrebbe semplicemente modificare il saldo di lettura/scrittura facendo crollare su e giù il tempo per svuotare il buffer. –

risposta

6

Secondo MSDN, ReaderWriterLockSlim favorisce gli scrittori. Ciò significa che quando ci sono lettori e scrittori in coda, gli scrittori avranno la preferenza.

Questo può produrre l'inattività del lettore, il codice di prova per riprodurre questo è here. Presumo che la fame può accadere solo se la scrittura è un'operazione lunga, che coinvolge l'interruttore di contesto del thread. Almeno è sempre riprodotto sulla mia macchina, quindi per favore dimmi se ho torto.

D'altra parte, ReaderWriterLock da .net 2.0 non produce né fame né scrittore, a costo di prestazioni ridotte. Here è il codice modificato dal campione precedente, per mostrare che non sta accadendo la fame.

Quindi, tornando alla tua domanda - dipende da quali funzionalità hai bisogno dal blocco RW. Serrature ricorsive, gestione delle eccezioni, timeout - corrispondenza più vicina a qualità di produzione Blocco RW che supporta tutto quanto sopra e favorisce i lettori sarebbe probabilmente ReaderWriterLock.

Inoltre, è possibile adottare il codice dall'articolo wiki che descrive first readers-writers problem, ma ovviamente è necessario implementare manualmente tutte le funzionalità richieste dall'alto e l'implementazione presenterà un problema di scrittore.

nucleo

Lock può probabilmente simile a questa:

class AutoDispose : IDisposable 
{ 
    Action _action; 
    public AutoDispose(Action action) 
    { 
    _action = action; 
    } 
    public void Dispose() 
    { 
    _action(); 
    } 
} 

class Lock 
{ 
    SemaphoreSlim wrt = new SemaphoreSlim(1); 
    int readcount=0; 

    public IDisposable WriteLock() 
    { 
    wrt.Wait(); 
    return new AutoDispose(() => wrt.Release()); 
    } 

    public IDisposable ReadLock() 
    { 
    if (Interlocked.Increment(ref readcount) == 1) 
     wrt.Wait(); 

    return new AutoDispose(() => 
    { 
     if (Interlocked.Decrement(ref readcount) == 0) 
     wrt.Release(); 
    }); 
    } 
} 

Confrontando le prestazioni di 3 implementazioni, utilizzando 3 lettore e 3 fili scrittore, utilizzando semplici in memoria operativa (con funzionamento a lungo blocco produrrebbero lettore-fame per RWLockSlim e scrittore-fame per la serratura su ordinazione):

Performance comparison

ho fatto in modo che ciclo carico di lavoro non viene svolto dal compilatore, ma ci potrebbero essere altre insidie ​​io non sono a conoscenza, in modo t prendi queste misure con un granello di sale. Il codice sorgente per i test è here.

+0

risposta grande e molto dettagliata! molto apprezzato - darò un'occhiata. –

Problemi correlati