Tôi đã xem xét kỹ mã của bạn và nó xuất hiện đúng với tôi. Một điều mà ngay lập tức nhảy ra ngoài với tôi là bạn đã sử dụng một mô hình được thiết lập để thực hiện thao tác khóa thấp. Tôi có thể thấy rằng bạn đang sử dụng version
làm loại khóa ảo. Ngay cả các số được phát hành và số lẻ được mua lại. Và kể từ khi bạn đang sử dụng một giá trị gia tăng đơn điệu cho khóa ảo, bạn cũng tránh được ABA problem. Tuy nhiên, điều quan trọng nhất là bạn tiếp tục lặp lại trong khi cố gắng đọc cho đến khi giá trị khóa ảo được xem là giống nhau trước lần đọc bắt đầu so với sau khi hoàn thành. Nếu không, bạn xem xét việc đọc này không thành công và thử lại tất cả. Vì vậy, vâng, công việc cũng được thực hiện trên logic cốt lõi.
Vậy vị trí của bộ tạo rào cản bộ nhớ là gì? Vâng, tất cả điều này có vẻ khá tốt là tốt. Tất cả các cuộc gọi Thread.MemoryBarrier
là bắt buộc. Nếu tôi đã phải nit-pick tôi sẽ nói rằng bạn cần thêm một trong các phương pháp Write
để nó trông như thế này.
public void Write(T value)
{
// locks are full barriers
lock (write)
{
++version; // ++version odd: write in progress
Thread.MemoryBarrier();
this.value = value;
Thread.MemoryBarrier();
++version; // ++version even: write complete
}
}
Cuộc gọi được thêm vào đây đảm bảo rằng ++version
và this.value = value
không được đổi chỗ. Bây giờ, đặc tả kỹ thuật ECMA cho phép loại lệnh đó sắp xếp lại. Tuy nhiên, việc thực hiện của Microsoft về CLI và phần cứng x86 đều đã có ngữ nghĩa dễ bay hơi khi viết nên nó sẽ không thực sự cần thiết trong hầu hết các trường hợp. Nhưng, những người hiểu biết, có lẽ nó sẽ là cần thiết trên thời gian chạy Mono nhắm mục tiêu cpu ARM.
Trên mặt số Read
tôi không thể tìm thấy lỗi nào. Trong thực tế, việc sắp xếp các cuộc gọi bạn có là chính xác nơi tôi sẽ đặt chúng. Một số người có thể tự hỏi tại sao bạn không cần một cái trước khi đọc ban đầu của version
. Lý do là bởi vì vòng lặp bên ngoài sẽ bắt được trường hợp khi lần đọc đầu tiên được lưu vào bộ nhớ cache vì giảm bớt chi tiết Thread.MemoryBarrier
.
Vì vậy, điều này đưa tôi đến một cuộc thảo luận về hiệu suất. Điều này thực sự nhanh hơn việc lấy khóa cứng trong phương thức Read
? Vâng, tôi đã làm một số thử nghiệm khá rộng rãi của mã của bạn để giúp trả lời điều đó. Câu trả lời là dứt khoát có! Điều này là khá nhanh hơn một chút so với tham gia một khóa cứng. Tôi đã thử nghiệm sử dụng Guid
làm loại giá trị vì nó là 128 bit và do đó lớn hơn kích thước từ gốc của máy (64 bit). Tôi cũng đã sử dụng một số biến thể khác nhau về số lượng nhà văn và độc giả. Kỹ thuật khóa thấp của bạn nhất quán và vượt trội đáng kể so với kỹ thuật khóa cứng. Tôi thậm chí đã thử một vài biến thể sử dụng Interlocked.CompareExchange
để đọc bảo vệ và tất cả chúng đều chậm hơn. Trong thực tế, trong một số trường hợp, nó thực sự chậm hơn so với lấy khóa cứng. Tôi phải trung thực. Tôi hoàn toàn không ngạc nhiên bởi điều này.
Tôi cũng đã thực hiện một số thử nghiệm hợp lệ đáng kể. Tôi đã tạo ra các bài kiểm tra sẽ chạy trong một thời gian khá lâu và không một lần tôi thấy một cuốn sách bị rách. Và sau đó như là một kiểm tra kiểm soát tôi sẽ tinh chỉnh phương pháp Read
theo cách như vậy mà tôi biết nó sẽ là không chính xác và tôi chạy thử nghiệm một lần nữa. Lần này, như mong đợi, những lần đọc rách bắt đầu xuất hiện ngẫu nhiên. Tôi chuyển mã trở lại những gì bạn có và những lần đọc bị rách biến mất; một lần nữa, như mong đợi. Điều này dường như để xác nhận những gì tôi đã mong đợi. Tức là, mã của bạn có vẻ chính xác. Tôi không có nhiều môi trường thời gian chạy và phần cứng để thử nghiệm (và tôi cũng không có thời gian) nên tôi không sẵn lòng cho nó 100% con dấu phê duyệt, nhưng tôi nghĩ tôi có thể cho bạn thực hiện hai ngón tay cái cho bây giờ.
Cuối cùng, với tất cả những gì đã nói, tôi vẫn sẽ tránh đặt sản phẩm này vào sản xuất. Vâng, nó có thể đúng, nhưng người tiếp theo phải duy trì mã có lẽ sẽ không hiểu nó. Ai đó có thể thay đổi mã và phá vỡ nó bởi vì họ không hiểu hậu quả của những thay đổi của họ. Bạn phải thừa nhận rằng mã này khá dễ vỡ. Ngay cả sự thay đổi nhỏ nhất cũng có thể phá vỡ nó.
Nhận xét và mã của bạn (thông tin/phiên bản) không đồng bộ. –
Cảm ơn, đã đăng bài! – naasking