2016-08-09 31 views
7

folgendes Beispiel:C# parallel Lesezugriff ohne zur Liste Kopieren

class Example 
{ 
    private readonly List<string> _list = new List<string>(); 
    private readonly object _lock = new object(); 

    public IReadOnlyList<string> Contents 
    { 
     get 
     { 
      lock (_lock) 
      { 
       return new List<string>(_list); 
      } 
     } 
    } 

    public void ModifyOperation(string example) 
    { 
     lock (_lock) 
     { 
      // ... 
      _list.Add(example); 
      // ... 
     } 
    } 
} 

Wie parallel Zugriff auf die Contents Liste lesen konnte, ohne das Kopieren der gesamten Liste erreicht werden? In C# gibt es gleichzeitig Collections, aber es gibt keine threadsichere Liste. In Java gibt es so etwas wie die CopyOnWriteArrayList.

+5

Wie wäre es [ 'ImmutableList '] (https://msdn.microsoft.com/ en-us/library/dn467185 (v = vs.111) .aspx) aus 'System.Collections.Immutable' Paket –

+0

Wie wäre es mit dem Blockieren der Sammlung? (https://msdn.microsoft.com/en-us/library/dd267312(v=vs.110).aspx) – derape

+0

Solange Sie 'ModifyOperation()' erlauben, während anderer Code (möglicherweise ein anderer Thread) aufgerufen werden hat Zugriff auf das von 'Contents' zurückgegebene Objekt, dann wird es nicht threadsicher, wenn Sie die zugrundeliegende' Liste 'zurücksenden, ohne eine Kopie zu erstellen (wie Sie es schon tun) –

Antwort

6

Meiner Meinung nach ist die ImmutableList<T> Klasse von System.Collections.Immutable Paket für solche Szenario perfekt. Es implementiert IReadOnlyList<T>, und da es unveränderlich ist, d. H. Nie geändert, können Sie es direkt aus dem Lesezugriff zurückgeben. Die Synchronisation benötigt wird zwischen den modifizierenden Operationen sein:

class Example 
{ 
    private ImmutableList<string> _list = ImmutableList<string>.Empty; 
    private readonly object _lock = new object(); 

    public IReadOnlyList<string> Contents => _list; 

    public void ModifyOperation(string example) 
    { 
     lock (_lock) 
     { 
      // ... 
      _list = _list.Add(example); 
      // ... 
     } 
    } 
} 
1

Lock-Free-Vorschlag ...

class Example 
{ 
    private ImmutableList<String> _list = ImmutableList<String>.Empty; 

    public IReadOnlyList<String> Contents { get { return _list; } } 

    public void ModifyOperation(String example) 
    { 
     ImmutableList<String> original; 
     ImmutableList<String> afterChange; 
     do 
     { 
      original = _list; 
      afterChange = _list.Add(example); 
     } 
     while (Interlocked.CompareExchange(ref _list, afterChange, original) != original); 
    } 
} 
+0

Sehr schön. Vielen Dank! – Nico