Хобрук: Ваш путь к мастерству в программировании

С# можно ли изменить приоритет получения блокировки?

Если есть несколько потоков, ожидающих одной и той же блокировки, возможно ли, чтобы основной поток имел более высокий приоритет при получении блокировки. Это означает, что если рабочие потоки переходят к оператору lock перед основным потоком, основной поток получит блокировку раньше других потоков, которые уже ожидают его.

17.10.2012

Ответы:


1

Нет, оператор lock сопоставляется с System.Threading.Monitor.Enter() (MSDN), и нет перегрузка, которая принимает параметр приоритета.

Самое близкое, что я могу придумать, это ReaderWriterLock(Slim), но я бы серьезно пересмотрел дизайн, который приводит к этому запросу. Вероятно, есть лучшие способы добиться того, что вам нужно.

17.10.2012
  • Ре. Я бы серьезно пересмотрел дизайн - этот запрос не похож на этот, например, in-mutex-locking" title="как отдать приоритет привилегированному потоку при блокировке мьютекса"> stackoverflow.com/questions/11666610/? Кажется 100% законным, как цель/замысел. Как бы вы изменили дизайн в таких случаях? Не кажется возможным... 17.02.2021

  • 2

    Через собственный оператор блокировки, нет. С помощью вашего собственного механизма блокировки, конечно, если вы готовы потратить время и усилия на его разработку.

    Вот мой проект решения. Это может работать или не работать, и может быть не очень эффективным, но это, по крайней мере, отправная точка:

    public class Lock
    {
        bool locked = false;
    
        private object key = new object();
        SortedDictionary<int, Queue<ManualResetEvent>> notifiers =
            new SortedDictionary<int, Queue<ManualResetEvent>>();
    
        ManualResetEvent specialNotifier = null;
    
        public void Lock()
        {
            lock (key)
            {
                if (locked)
                {
                    ManualResetEvent notifier = new ManualResetEvent(false);
    
                    int priority = getPriorityForThread();
    
                    Queue<ManualResetEvent> queue = notifiers[priority];
                    if (queue == null)
                    {
                        queue = new Queue<ManualResetEvent>();
                        notifiers[priority] = queue;
                    }
    
                    queue.Enqueue(notifier);
    
                    notifier.WaitOne();
                }
                else
                {
                    locked = true;
                }
            }
        }
    
        private static int getPriorityForThread()
        {
            return 0;
        }
    
        public void Release()
        {
            lock (key)
            {
                foreach (var queue in notifiers.Values)
                {
                    if (queue.Any())
                    {
                        var notifier = queue.Dequeue();
                        notifier.Set();
                        return;
                    }
                }
                locked = false;
            }
        }
    }
    
    17.10.2012
  • Просто любопытно, есть ли причина, по которой нельзя использовать IDisposable? 09.02.2016
  • @wwahammy Нет причин, нет. 09.02.2016

  • 3

    Вот еще одно решение. У меня много строк, но это довольно просто. Функция DoSomethingSingle будет вызываться только по одному потоку за раз, и те, у кого установлен флаг highPriority, получат преимущество.

        static int numWaiting = 0;
        static object single = new object();
    
        ResultType DoSomething(string[] argList, bool highPriority = false)
        {
            try
            {
                if (highPriority)
                {
                    Interlocked.Increment(ref numWaiting);
                }
    
                for (;;)
                {
                    lock (single)
                    {
                        if (highPriority || numWaiting == 0)
                        {
                            return DoSomethingSingle(argList);
                        }
                    }
                    // Sleep gives other threads a chance to enter the lock
                    Thread.Sleep(0);
                }
            }
            finally
            {
                if (highPriority)
                {
                    Interlocked.Decrement(ref numWaiting);
                }
            }
        }
    

    Это позволяет использовать два уровня приоритета. Гарантируется, что поток с низким приоритетом получит доступ к ресурсу только в том случае, если его не ожидают потоки с высоким приоритетом.

    изменить: изменить на блокировку incr/dec

    01.07.2016
    Новые материалы

    Понимание СТРУКТУРЫ ДАННЫХ И АЛГОРИТМА.
    Что такое структуры данных и алгоритмы? Термин «структура данных» используется для описания того, как данные хранятся, а алгоритм используется для описания того, как данные сжимаются. И данные, и..

    Как интегрировать модель машинного обучения на ios с помощью CoreMl
    С выпуском новых функций, таких как CoreML, которые упростили преобразование модели машинного обучения в модель coreML. Доступная модель машинного обучения, которую можно преобразовать в модель..

    Создание успешной организации по науке о данных
    "Рабочие часы" Создание успешной организации по науке о данных Как создать эффективную группу по анализу данных! Введение Это обзорная статья о том, как создать эффективную группу по..

    Технологии и проблемы будущей работы
    Изучение преимуществ и недостатков технологий в образовании В быстро меняющемся мире технологии являются решающим фактором в формировании будущего работы. Многие отрасли уже были..

    Игорь Минар из Google приедет на #ReactiveConf2017
    Мы рады сообщить еще одну замечательную новость: один из самых востребованных спикеров приезжает в Братиславу на ReactiveConf 2017 ! Возможно, нет двух других кланов разработчиков с более..

    Я собираюсь научить вас Python шаг за шагом
    Привет, уважаемый энтузиаст Python! 👋 Готовы погрузиться в мир Python? Сегодня я приготовил для вас кое-что интересное, что сделает ваше путешествие более приятным, чем шарик мороженого в..

    Альтернатива шаблону исходящих сообщений для архитектуры микросервисов
    Познакомьтесь с двухэтапным сообщением В этой статье предлагается альтернативный шаблон для папки Исходящие : двухэтапное сообщение. Он основан не на очереди сообщений, а на..