Почему ReaderWriterLockSlim вызывает Sleep () внутри EnterReadLock ()?

2

Я пытаюсь внедрить потокобезопасный пул ресурсов, к которому можно быстро получить доступ и который получает только случайные обновления. Для этого я использую ReaderWriterLockSlim с методом расширения для входа и выхода из блокировки чтения. В то время как профилирование использования потока было неожиданно очень низким.

Я проверил, что в пул не было записи, поэтому EnterWriteLock() никогда не вызывался.

internal Mesh GetMesh(string name)
{
    using (CacheLock.Read())
    {
        if (MeshDictionary.TryGetValue(name, out var m))
        {
            return m;
        }
    }
    // <snip>
}
public static ReadLock Read(this ReaderWriterLockSlim l)
{
    return new ReadLock(l);
}
internal class ReadLock : IDisposable
{
    private readonly ReaderWriterLockSlim _lockObject;
    public ReadLock(ReaderWriterLockSlim l)
    {
        _lockObject = l;
        l.EnterReadLock();
    }
    public void Dispose()
    {
        _lockObject.ExitReadLock();
    }
}

Во время профилирования я обнаружил, что большинство потоков тратит около 25% своего времени внутри EnterReadLock(). Внутренний сон этой функции занимает около 19%, а остальное время используется для активного вращения и других накладных расходов. Я ожидал бы, что EnterReadLock вообще не спит и только вращается в течение короткого времени. Есть ли способ улучшить использование и сократить время ожидания?

Теги:
multithreading
locking
readerwriterlockslim

1 ответ

0

Тонкие версии потоковых компонентов используют спин-блокировки, которые бывают быстрыми, но интенсивно используют процессор. Если вы ожидаете ожидания любой длительности, используйте более старый ReaderWriterLock.

  • 0
    Почему я должен ожидать спать? Я не ожидаю сна, так как я не вызываю EnterWriteLock. Я ожидал бы, что EnterReadLock вообще не спит и только вращается в течение короткого времени. Не могли бы вы уточнить, почему EnterReadLock вызывает sleep, даже если ни один из писателей не удерживает блокировку?
  • 1
    Если SpinLock не удается получить в течение короткого периода времени, он переходит в режим ожидания для экономии ресурсов ЦП. Если вы используете старые типы, то вы ожидаете мьютексов собственных окон, которые взаимодействуют с планировщиком задач (т. Е. Поток блокируется во время ожидания и разблокируется, когда ресурс освобождается). Это медленнее, но имеет меньше системных издержек.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню