Вложенная блокировка к той же объектной производительности

Действительно ли это - стоимость производительности для использования вложенных блокировок для того же объекта.

Скажите, что мы имеем:

    public void AddRange(IEnumeratable<Item> items)
    {
        lock (_syncObject)
        {
            foreach (Item item in items)
            {
                InsertItem(item);
            }
        }
    }

    public void InsertItem(Item item)
    {
        lock (_syncObject)
        {
            //..
        }
    }

Это должно хорошо сделать так "сторону производительности"?

Заранее спасибо.

9
задан Pasi Savolainen 22 April 2010 в 15:47
поделиться

3 ответа

У блокировки есть затраты, я предлагаю вам реализовать свой код следующим образом:

public void AddRange(IEnumeratable<Item> items)
{
    lock (_syncObject) // Locking only once.
    {
        foreach (Item item in items)
        {
            InsertItemImpl(item);
        }
    }
}

private void InsertItemImpl(Item item)
{
     // inserting the item
}

public void InsertItem(Item item)
{
    lock (_syncObject)
    {
        InsertItemImpl(item);
    }
}
7
ответ дан 4 December 2019 в 21:09
поделиться

Я не знаю, как это повлияет на производительность, но когда мы ожидаем, что это снизит производительность, я предлагаю вам реализовать свой код наоборот:

public void InsertItem(Item item)
{
    AddRange(new IEnumeratable({item}))
}

public void AddRange(IEnumeratable<Item> items)
{
    lock (_syncObject)
    {
        foreach (Item item in items)
        {
            // Insert code ..
        }
    }
}

@AddRange (новый IEnumeratable ({item})): Я не специалист по синтаксису, поэтому поправьте меня, если это не так!

1
ответ дан 4 December 2019 в 21:09
поделиться

блокировка платная. у него есть , чтобы проверить некоторые вещи перед возвращением. Сколько всего и что нужно делать, зависит от реализации. Я бы предположил , что такое использование является обычным явлением, и MS провела некоторую оптимизацию для этого варианта использования.

Я бы по-прежнему рекомендовал вам иметь отдельную реализацию AddRange, чтобы все операции выполнялись за один раз. Это, конечно, зависит от остальной части интерфейса класса (есть ли слушатели и могут ли они получать сообщения о добавлении нескольких объектов и т. Д.).

Это довольно простой тестовый пример, проделайте несколько миллионов вложенных блокировок (что вы предлагаете) и то же самое с другой блокировкой.

Обратите внимание на другой возможный порядок, если вы используете невложенную блокировку, вы можете получить объект в середине добавляемого диапазона:

AddRange _sync1
  AddItem _sync2
  AddItem _sync2
  --- interruption, other thread calls:
  AddItem _sync2
  --- AddRange again:
  AddItem _sync2

При синхронизации с одним _syncObject никто не может прервать, потому что блокировка уже установлена. удерживается другой нитью.

2
ответ дан 4 December 2019 в 21:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: