SpinWait в обновлении без блокировки
Читая Потоки Албахари в C#, я заметил, что шаблон "Блокировка бесплатного обновления" использует SpinWait
в конце цикла:
static void LockFreeUpdate<T> (ref T field, Func <T, T> updateFunction)
where T : class
{
var spinWait = new SpinWait();
while (true)
{
// read
T snapshot1 = field;
// apply transformation
T calc = updateFunction (snapshot1);
// compare if not preempted
T snapshot2 = Interlocked.CompareExchange (ref field, calc, snapshot1);
// if succeeded, we're done
if (snapshot1 == snapshot2) return;
// otherwise spin
spinWait.SpinOnce();
}
}
Обратите внимание spinWait.SpinOnce()
позвоните в конце. Нужен ли этот вызов только для того, чтобы получить поток в однопоточной среде, или он имеет дополнительную цель?
1 ответ
Краткий ответ... Да. Намерение SpinWait
разрешить передачу потока в систему, чтобы избежать потери ресурсов из-за SpinLock
,
Из MSDN
https://msdn.microsoft.com/en-us/library/system.threading.spinwait(v=vs.110).aspx
SpinWait инкапсулирует обычную логику вращения. На однопроцессорных компьютерах выходы всегда используются вместо ожиданий, а на компьютерах с процессорами Intel, использующими технологию Hyper-Threading, это помогает предотвратить истощение аппаратных потоков. SpinWait заключает в себе хорошую смесь прядения и настоящей урожайности.
SpinWait является типом значения, что означает, что низкоуровневый код может использовать SpinWait, не опасаясь ненужных накладных расходов. SpinWait обычно не полезен для обычных приложений. В большинстве случаев вам следует использовать классы синхронизации, предоставляемые.NET Framework, например Monitor. Однако для большинства целей, где требуется ожидание вращения, тип SpinWait должен быть предпочтительнее метода SpinWait.