2016-08-09 17 views
7

Hãy xem xét ví dụ sau:C# song song đọc truy cập vào danh sách mà không cần sao chép

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

Làm thế nào có thể song song đọc truy cập vào Danh sách Contents thể đạt được mà không cần sao chép toàn bộ Danh mục sách? Trong C# có đồng thời Collections, nhưng không có danh sách an toàn chủ đề. Trong Java có một cái gì đó giống như CopyOnWriteArrayList.

+5

Làm thế nào về [ 'ImmutableList '] (https://msdn.microsoft.com/ en-us/library/dn467185 (v = vs.111) .aspx) từ gói 'System.Collections.Immutable' –

+0

Điều gì về việc chặn bộ sưu tập? (https://msdn.microsoft.com/en-us/library/dd267312(v=vs.110).aspx) – derape

+0

Miễn là bạn cho phép 'ModifyOperation()' được gọi trong khi mã khác (có thể là một chuỗi khác) có quyền truy cập đối tượng được trả về từ 'Contents' thì nó sẽ không phải là luồng an toàn nếu bạn trả về' List 'bên dưới mà không tạo một bản sao (như bạn đã làm) –

Trả lời

6

Theo tôi, lớp ImmutableList<T> từ gói System.Collections.Immutable là hoàn hảo cho trường hợp như vậy. Nó thực hiện IReadOnlyList<T> và vì nó không thay đổi, tức là không bao giờ sửa đổi, bạn có thể trả lại trực tiếp từ trình đọc. Việc đồng bộ hóa chỉ cần thiết sẽ được giữa các hoạt động sửa đổi:

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

Khóa miễn gợi ý ...

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

Rất đẹp. Cảm ơn! – Nico

Các vấn đề liên quan