Trong trường hợp số lần đọc vượt quá số lần ghi, hoặc (tuy nhiên thường xuyên) việc ghi không đồng thời , cách tiếp cận sao chép trên ghi có thể phù hợp.
Việc thực hiện dưới đây là
- không khóa
- cực kỳ nhanh để đọc đồng thời , ngay cả khi các sửa đổi đồng thời đang diễn ra - bất kể chúng mất bao lâu
- bởi vì "ảnh chụp nhanh" là bất biến, nguyên tử không khóa là có thể, tức là
var snap = _list; snap[snap.Count - 1];
sẽ không bao giờ (tốt, ngoại trừ một danh sách trống tất nhiên), và bạn cũng nhận được liệt kê an toàn theo chủ đề với ngữ nghĩa chụp nhanh miễn phí .. làm thế nào tôi YÊU sự bất biến!
- triển khai rộng rãi , áp dụng cho mọi cấu trúc dữ liệu và mọi loại sửa đổi
- Chết đơn giản , dễ kiểm tra, gỡ lỗi, xác minh bằng cách đọc mã
- có thể sử dụng trong .Net 3.5
Để sao chép trên ghi hoạt động, bạn phải giữ cấu trúc dữ liệu của mình một cách hiệu quả bất biến , tức là không ai được phép thay đổi chúng sau khi bạn cung cấp chúng cho các luồng khác. Khi bạn muốn sửa đổi, bạn
- nhân bản cấu trúc
- sửa đổi trên bản sao
- trao đổi nguyên tử trong tham chiếu đến bản sao được sửa đổi
Mã
static class CopyOnWriteSwapper
{
public static void Swap<T>(ref T obj, Func<T, T> cloner, Action<T> op)
where T : class
{
while (true)
{
var objBefore = Volatile.Read(ref obj);
var newObj = cloner(objBefore);
op(newObj);
if (Interlocked.CompareExchange(ref obj, newObj, objBefore) == objBefore)
return;
}
}
}
Sử dụng
CopyOnWriteSwapper.Swap(ref _myList,
orig => new List<string>(orig),
clone => clone.Add("asdf"));
Nếu bạn cần hiệu năng cao hơn, nó sẽ giúp làm sáng tỏ phương thức, ví dụ: tạo một phương thức cho mọi loại sửa đổi (Thêm, Xóa, ...) bạn muốn và mã cứng các con trỏ hàm cloner
và op
.
NB # 1 Bạn có trách nhiệm đảm bảo không ai sửa đổi cấu trúc dữ liệu bất biến (được cho là). Không có gì chúng ta có thể làm trong một triển khai chung để ngăn chặn điều đó, nhưng khi chuyên môn hóa List<T>
, bạn có thể bảo vệ chống lại sửa đổi bằng List.AsReadOnly ()
NB # 2 Hãy cẩn thận về các giá trị trong danh sách. Cách tiếp cận sao chép trên chỉ bảo vệ tư cách thành viên danh sách của họ, nhưng nếu bạn không đặt chuỗi, nhưng một số đối tượng có thể thay đổi khác trong đó, bạn phải quan tâm đến an toàn luồng (ví dụ: khóa). Nhưng đó là trực giao với giải pháp này và ví dụ: khóa các giá trị có thể thay đổi có thể dễ dàng sử dụng mà không gặp vấn đề gì. Bạn chỉ cần nhận thức được nó.
NB # 3 Nếu cấu trúc dữ liệu của bạn rất lớn và bạn sửa đổi nó thường xuyên, phương pháp sao chép toàn bộ ghi có thể bị cấm cả về mức tiêu thụ bộ nhớ và chi phí sao chép CPU liên quan. Trong trường hợp đó, bạn có thể muốn sử dụng Bộ sưu tập bất biến của MS thay thế.