2016-08-09 14 views
7

Rozważmy następujący przykład:C# równoległy dostęp do odczytu do listy bez kopiowania

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); 
      // ... 
     } 
    } 
} 

Jak można przeczytać równoległy dostęp do listy Contents zostać osiągnięty bez kopiowania całej listy? W języku C# są współbieżne Collections, ale nie ma listy bezpiecznych wątków. W Javie jest coś takiego jak CopyOnWriteArrayList.

+5

Jak o [ 'ImmutableList '] (https://msdn.microsoft.com/ en-us/library/dn467185 (v = vs.111) .aspx) z pakietu 'System.Collections.Immutable' –

+0

Co z blokowaniem kolekcji? (https://msdn.microsoft.com/en-us/library/dd267312(v=vs.110).aspx) – derape

+0

Dopóki zezwolisz na wywołanie 'ModifyOperation()', podczas gdy inny kod (prawdopodobnie inny wątek) ma dostęp do obiektu zwróconego z 'Contents', to nie będzie bezpieczny dla wątków, jeśli zwrócisz bazową' Listę 'bez tworzenia kopii (tak jak już to robisz) –

Odpowiedz

6

Moim zdaniem klasa ImmutableList<T> z pakietu System.Collections.Immutable jest idealna do takiego scenariusza. Implementuje IReadOnlyList<T>, a ponieważ jest niezmienny, tj. Nigdy nie jest modyfikowany, możesz go bezpośrednio zwrócić z read accessora. Jedynym synchronizacja potrzebne będzie między operacji modyfikujących:

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

Blokada wolna sugestia ...

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

Bardzo ładne. Dzięki! – Nico

Powiązane problemy