Действительно ли это - стоимость производительности для использования вложенных блокировок для того же объекта.
Скажите, что мы имеем:
public void AddRange(IEnumeratable<Item> items)
{
lock (_syncObject)
{
foreach (Item item in items)
{
InsertItem(item);
}
}
}
public void InsertItem(Item item)
{
lock (_syncObject)
{
//..
}
}
Это должно хорошо сделать так "сторону производительности"?
Заранее спасибо.
У блокировки есть затраты, я предлагаю вам реализовать свой код следующим образом:
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);
}
}
Я не знаю, как это повлияет на производительность, но когда мы ожидаем, что это снизит производительность, я предлагаю вам реализовать свой код наоборот:
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})): Я не специалист по синтаксису, поэтому поправьте меня, если это не так!
блокировка
платная. у него есть , чтобы проверить некоторые вещи перед возвращением. Сколько всего и что нужно делать, зависит от реализации. Я бы предположил , что такое использование является обычным явлением, и MS провела некоторую оптимизацию для этого варианта использования.
Я бы по-прежнему рекомендовал вам иметь отдельную реализацию AddRange, чтобы все операции выполнялись за один раз. Это, конечно, зависит от остальной части интерфейса класса (есть ли слушатели и могут ли они получать сообщения о добавлении нескольких объектов и т. Д.).
Это довольно простой тестовый пример, проделайте несколько миллионов вложенных блокировок (что вы предлагаете) и то же самое с другой блокировкой.
Обратите внимание на другой возможный порядок, если вы используете невложенную блокировку, вы можете получить объект в середине добавляемого диапазона:
AddRange _sync1
AddItem _sync2
AddItem _sync2
--- interruption, other thread calls:
AddItem _sync2
--- AddRange again:
AddItem _sync2
При синхронизации с одним _syncObject никто не может прервать, потому что блокировка уже установлена. удерживается другой нитью.