Многопоточность: разница между типами блокирующих объектов

Вопрос:

Пожалуйста, объясните разницу между этими двумя типами блокировки.

У меня есть List который я хочу получить в потокобезопасном:

var tasks = new List<string>();

1.

var locker = new object();
lock (locker)
{
tasks.Add("work 1");
}

2.

lock (tasks)
{
tasks.Add("work 2");
}

Мои мысли:

  1. Предотвращает одновременный запуск двух разных потоков из заблокированного блока кода.

Но если другой поток выполняет другой метод, когда он пытается получить доступ к task – этот тип lock не поможет.

  1. Блокирует экземпляр List<> поэтому другие потоки других методов будут заблокированы до тех пор, пока я не разблокирую tasks.

Я прав или ошибаюсь?

Лучший ответ:

(2) блокирует только другой код, который явно вызывает lock (tasks). Как правило, это нужно делать только в том случае, если вы знаете, что задачи являются частным полем и, таким образом, могут применяться во всем вашем классе, что lock (tasks) означает операции блокировки в списке. Это может быть хорошим ярлыком, когда блокировка концептуально связана с доступом к коллекции, и вам не нужно беспокоиться об открытом доступе к замку. Вы не получаете это “бесплатно”; он должен быть явно использован так же, как блокировка на любом другом объекте.

Ответ №1

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

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

Оцените статью
TechArks.Ru
Добавить комментарий