Dưới đây là việc thực hiện một phương pháp lồng vào nhau dựa trên Interlocked.CompareExchange
.
Có nên cho mã này sử dụng SpinWait
spin trước khi nhắc lại không?
public static bool AddIfLessThan(ref int location, int value, int comparison)
{
int currentValue;
do
{
currentValue = location; // Read the current value
if (currentValue >= comparison) return false; // If "less than comparison" is NOT satisfied, return false
}
// Set to currentValue+value, iff still on currentValue; reiterate if not assigned
while (Interlocked.CompareExchange(ref location, currentValue + value, currentValue) != currentValue);
return true; // Assigned, so return true
}
Tôi đã thấy SpinWait
được sử dụng trong kịch bản này, nhưng lý thuyết của tôi là nó không cần thiết. Rốt cuộc, vòng lặp chỉ chứa một số ít các hướng dẫn và luôn có một tiến trình thực hiện.
Giả sử rằng hai luồng đang chạy đua để thực hiện phương thức này và luồng đầu tiên thành công ngay lập tức, trong khi luồng thứ hai ban đầu không có thay đổi và phải nhắc lại. Không có ứng cử viên nào khác, liệu luồng thứ hai có thể thất bại ở lần thử thứ hai không?
Nếu luồng thứ hai của ví dụ không thể thất bại trong lần thử thứ hai, thì chúng ta có thể đạt được gì với a SpinWait
? Cạo sạch một vài chu kỳ trong trường hợp không chắc là một trăm luồng đang chạy đua để thực hiện phương pháp?
SpinOnce
để ngăn hệ điều hành một luồng có khả năng bị bỏ đói. Xem stackoverflow.com/questions/37799381/ khăn
Interlocked
. Để làm rõ, tôi chỉ quan tâm đến việc một cái SpinWait
có ý nghĩa hay không , ví dụ như để lưu chu kỳ CPU một cách có ý nghĩa hoặc (cảm ơn @MatthewWatson!) Ngăn chặn một hệ điều hành đơn luồng bị bỏ đói.
SpinWait
thậm chí sẽ không làm giảm mức tiêu thụ năng lượng, vì cùng một số lần thử sẽ được thực hiện! (Với hai luồng, đó là một lần thử cho lần đầu tiên và hai lần cho luồng thứ hai.)