Пожалуйста, объясните разницу между этими двумя типами блокировки.
У меня есть List
который я хочу получить в потокобезопасном:
var tasks = new List<string>();
1.
var locker = new object();
lock (locker)
{
tasks.Add("work 1");
}
2.
lock (tasks)
{
tasks.Add("work 2");
}
Мои мысли:
- Предотвращает одновременный запуск двух разных потоков из заблокированного блока кода.
Но если другой поток выполняет другой метод, когда он пытается получить доступ к task
– этот тип lock
не поможет.
- Блокирует экземпляр
List<>
поэтому другие потоки других методов будут заблокированы до тех пор, пока я не разблокируюtasks
.
Я прав или ошибаюсь?
(2) блокирует только другой код, который явно вызывает lock (tasks)
. Как правило, это нужно делать только в том случае, если вы знаете, что задачи являются частным полем и, таким образом, могут применяться во всем вашем классе, что lock (tasks)
означает операции блокировки в списке. Это может быть хорошим ярлыком, когда блокировка концептуально связана с доступом к коллекции, и вам не нужно беспокоиться об открытом доступе к замку. Вы не получаете это “бесплатно”; он должен быть явно использован так же, как блокировка на любом другом объекте.
Они делают то же самое. Любой другой код, который пытается изменить список без блокировки одного и того же объекта, вызовет потенциальные условия гонки.
Лучше всего было бы инкапсулировать список в другой объект, который получает блокировку перед выполнением каких-либо операций в базовом списке, а затем любой другой код может использовать простые методы вызова на объекте-оболочке, не беспокоясь о получении блокировки.