Search
Write a publication
Pull to refresh
9
0
Андрей Грачев @gigavat38

Пользователь

Send message
Я понимаю, что вы использовали не случайно. Но атамарно изменять её в других местах с учетом знака я не придумал как (HighCount).

Да, на глаз я тоже вижу возможный рассинхрон. Но сколько тесты не гонял, не смог получить проблему. Поэтому залил такой вариант.
Обновил код в github и сборку nuget с учетом ваших комментариев.
Спасибо. В ближайшее время постараюсь применить ваши советы!
Наверно без экспериментов не обойтись…
Хочу сказать, что в своей практике я не применяю PriorityLock для долгих ожиданий и не получал просадки производительности из-за этого.

Если у вас есть желание, пожалуйста приведите пример кода, который будет правильнее чем этот:
var spin = new SpinWait();
while (Interlocked.CompareExchange(ref mgr.LowCount, 0, 0) != 0)
    spin.SpinOnce();
По поводу NextSpinWillYield не соглашусь, написано использовать это для двухэтапной операции ожидания. У меня контекст использования SpinWait ограничен только ожиданием счетчика.

А вот про создание SpinWait внутри метода соглашусь, изучил исходники, где применяется SpinWait, действительно стоит делать так как вы сказали.
Прокомментируйте пожалуйста чем плохо держать SpinWait полем в классе? Сам не могу предложить аргументов против.

По поводу второго, согласно статье SpinWait настолько умен, что может работать как в быстром, так и в долгом ожидании. Но понятно, что чем короче операции внутри лока, тем лучше.
Как я понимаю KamushekORIGINAL говорит об ошибке платформы, получении lock convoy. Но думаю не стоит записывать это на нашу совесть. А если такое произошло, видимо стоит менять архитектуру на неблокирющие операции.
Приложение из примера автоматизирует пользовательские шаблоны, оно манипулирует большим количеством потоков и большим количеством тяжелых процессов (ограничено лишь ресурсами компьютера). Менеджер из примера обрабатывает задания, при этом должен держать несколько коллекций в синхронизированном состоянии.

На самом деле даже используя обычный lock это не было узким местом. PriorityLock появился для решения проблем с UI. Архитектурно задачу я решил позже, вынес UI в отдельный процесс, потому что понял что основные фризы интерфейса создавал GC.

По поводу полезных расширений, я обожаю Custom Document Well из Productivity Power Tools.

Солгасен с вами, я тоже использую AsyncEx.
Но на NeoSmart.AsyncLock наткнулся при поиске переиспользования асинхронного лока. Ну и не мог не написать, что оно вообще не работает как lock.
Я немного о другом случае говорил: если внутри синхронного лока написать await — это гарантированнная проблема. Поэтому компилятор не дает внутри обычного lock писать await.
В исходниках SemaphoreSlim.WaitAsync использование lock находится в синхронной части кода, внутри lock там все детерминированно и максимально быстро выйдет из под него.
MonkAlex все правильно написал.
От себя лишь добавлю, что async/await — это механизм неблокирующих операций, но никто не отменяет необходимость критических секций в асинхронном коде. И использование синхронных методов синхронизации в асинхронном коде может плохо кончится, потому что Task != Thread, и зайдя в критическую секцию, таска может отпустить поток, а другая таска похватит поток и повторно зайдет в критическую секцию (в контексте использования PriorityLock, другие примитивы не проверял). Поэтому необходимы асинхронные методы синхронизации.
В ReadWriteLock сразу несколько читателей могут зайти внутрь критической секции. PriorityLock позволяет только одному потоку заходить в критическую секцию как обычный lock, но имеет два приоритета примерно как в ReadWriteLock.

А что вас смущает в async lock?
Спасибо за критику. Да, наверно пример не удачный. Задержки по несколько секунд исчезли после написания PriorityLock, но все равно вы правы, приоритетные очереди уместнее.
Тем не менее я уверен каждый найдет для себя сценарии использования такого примитива, я например много где его применяю.

По поводу производительности, я раньше тоже думал что SpinOnce это нечто злое, но как показала практика, SpinOnce не нагружает процессор никак, при этом дает процессорное время другим потокам в нормальном порядке. К тому же в комбинации с семафорами, SpinOnce не вызывается во всех ожидающих потоках.

Information

Rating
Does not participate
Location
Россия
Registered
Activity