ReaderWriterLockSlim vs. Monitor - PullRequest
       33

ReaderWriterLockSlim vs. Monitor

5 голосов
/ 02 января 2009

У меня есть IDictionary<TKey,TValue> реализация, которая внутренне содержит n Dictionary<TKey, TValue> и распределяет эти вставки с помощью HashCode ключа в отдельные словари. С 16 словарями количество столкновений на 4-ядерном компьютере довольно мало.

Для параллельных вставок я заблокировал метод Add с помощью ReaderWriterLockSlim, заблокировав только отдельный подсловарь:

  public void Add(TKey key, TValue value)
        {
            int poolIndex = GetPoolIndex(key);
            this.locks[poolIndex].EnterWriteLock();
            try
            {
                this.pools[poolIndex].Add(key, value);
            }
            finally
            {
                this.locks[poolIndex].ExitWriteLock();
            }
        }

При вставке элементов с четырьмя потоками, я получил только около 32% использования процессора и плохую производительность. Поэтому я заменил ReaderWriterLockSlim на Monitor (т.е. ключевое слово lock). Загрузка ЦП была почти на 100%, а производительность более чем удвоилась.

Мой вопрос: почему увеличилась загрузка процессора? Количество столкновений не должно было измениться. Что заставляет ReaderWriterLock.EnterWriteLock ждать так много раз?

Ответы [ 3 ]

13 голосов
/ 03 января 2009

Для загрузки только для записи монитор дешевле, чем ReaderWriterLockSlim, однако, если вы имитируете нагрузку чтения + записи, когда чтение намного больше, чем запись, то ReaderWriterLockSlim должен выполнить Monitor.

0 голосов
/ 02 января 2009

Как узнать, что послужило причиной плохой работы? Вы не можете угадать это, единственный способ - выполнить какое-то профилирование.

Как вы обрабатываете блокировку для родительской коллекции или она постоянна?

Может быть, вам нужно добавить отладочный вывод и посмотреть, что на самом деле происходит?

0 голосов
/ 02 января 2009

Я не гуру, но я предполагаю, что RWLS больше ориентирован на сильную конкуренцию (например, сотни потоков), тогда как Monitor больше настроен на решение этих одноразовых проблем синхронизации.

Лично я использую класс TimerLock, который использует Monitor.TryEnter с параметром тайм-аута.

...