2013-10-22 17 views

Trả lời

12

Sử dụng khóa không quá mức cần thiết. Đó là yêu cầu.

Các loại cấu trúc như System.Decimal không bao giờ là nguyên tử, nó cũng không phù hợp với kích thước từ cpu gốc. Đó là lý do tại sao Interlocked không có quá tải cho nó.

3

No. Biểu diễn bên trong của decimal quá phức tạp để sửa đổi được thực hiện với hướng dẫn nguyên tử ở cấp CPU (đó là những gì Interlocked thực hiện hầu hết thời gian và đó là những gì bạn quan tâm).

Khi CPU không thể xử lý nguyên tử một số khóa bằng tay số lượng là lựa chọn duy nhất. Bạn có thể chọn nguyên thủy đồng bộ hóa (ví dụ: lock so với một mutex) nhưng đó là nó.

0

Bạn vẫn có thể sử dụng InterLocked, nhưng sau đó bạn phải chuyển đổi số thập phân thành số Int64. Với quá trình chuyển đổi, bạn phải quyết định số lượng vị trí thập phân bạn muốn giữ cho độ chính xác. Ví dụ: bạn muốn giữ 4 chữ số thập phân, bạn có thể làm như sau:

 //Declare up front accessible from all threads 
     Int64 totalAmount = 0; 

     //Inside the thread you do this 
     var amount = (Int64)(decimalAmount * 10000); //10.000 is to preserve 4 decimal places 
     Interlocked.Add(ref totalAmount, amount); 

     //After all threads have finished, go back to decimal type. 
     var totalDecimalAmount = totalAmount/10000; 

Lưu ý rằng bạn sẽ mất chính xác, tùy thuộc vào số lượng chữ số thập phân bạn muốn giữ. Và Decimal.MaxValue79,228,162,514,264,337,593,543,950,335 trong khi Int64.MaxValue9,223,372,036,854,775,807. Vì vậy, số lượng rất lớn sẽ không phù hợp. Bảo quản 4 chữ số thập phân, số lớn nhất trước khi tràn Int64 sẽ là 9,223,372,036,854,775,807/10000 = 922,337,203,685,477

Tôi sử dụng số này theo số ở đây sẽ không bao giờ vượt quá 1.000.000.000 và tôi chắc chắn rằng sử dụng Interlocked theo cách này sẽ nhanh hơn trong vòng lặp Parallel.For sử dụng lock hoặc mutex.

0

Nếu bạn không nhớ giữ tổng như một đối tượng bọc decimal, bạn có thể sử dụng phương pháp này:

private static object myTotal = 0M; 
static void InterlockedAddTotal(decimal val) { 
    object next; 
    object current; 
    do { 
     current = myTotal; 
     next = val + (decimal)current; 
    } while (Interlocked.CompareExchange(ref myTotal, next, current) != current); 
} 

Mặc dù phương pháp này không sử dụng một khóa, nó kết thúc tốt đẹp decimal trong một đối tượng, có thể mang theo ý nghĩa hiệu suất của riêng nó. Tùy thuộc vào tình hình, việc sử dụng khóa có thể rẻ hơn.

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