Это пара оптимизированных рецептов, которые я придумал после прочтения других ответов. Не имеет прямого отношения к вопросу, но добавляет сюда, так как именно здесь приземлились похожие поиски. Пытался сохранить это значение a > b
или a >= b
, чтобы оно соответствовало исходному вопросу. И сделать их общими, чтобы не отклонять описания от других связанных проблем. Оба могут быть обернуты в методы.
Оптимизация - монотонная b
Если это единственная операция, которая выполняется для b
или b
в противном случае монотонно возрастает, вы можете оптимизировать блокировку присваивания и повторных попыток, где a > b == false
:
int initial;
do
{
initial = b;
}
while ((a > initial) && Interlocked.CompareExchange(ref b, a, initial) != initial);
Если a > b == false
, то после повторной попытки не будет true
(b
только увеличивается), и обмен можно пропустить, так как b
это не повлияет.
Связанная с оптимизацией проблема: слабое регулирование
Действие signal()
следует вызывать один раз каждый раз, когда локальная переменная a
(например, отсчет системного времени) увеличивается на некоторую константу threshold >= 1
с момента последнего вызова signal()
. Здесь b
— это пороговый заполнитель по сравнению с a
и устанавливается равным a + threshold
, если a >= b
. Только победившая нить должна вызывать signal()
.
var initial = b;
if ((a > initial) && Interlocked.CompareExchange(ref b, a + threshold, initial) == initial)
{
signal();
}
Здесь b
снова является монотонным, но теперь мы можем полностью отказаться от цикла повторных попыток, так как мы хотим только знать, выиграл ли локальный поток гонку с другими потоками, соблюдая threshold
. Этот метод эффективно блокирует сигнализацию любого другого потока в пределах определенного порога.
Предостережения по регулированию
Этот не сработает, если вам нужен строгий дроссель, то есть наименьшее a
, где a >= b
, поэтому в заголовке свободная. Это также не сработает, если вам нужно сообщить только о последнем из серии тесно сгруппированных a
s — то, что можно назвать debouncing, родственная, но отдельная проблема.
person
Marc L.
schedule
20.08.2018