SyncLock на двух объектах
Предположим, у меня есть два объекта a и b.
Я хочу синхронизировать оба объекта.
Это возможно? Это можно сделать с помощью вложенных операторов SyncLock? Каковы опасности такой операции?
редактировать
Возможно, я должен спросить, как можно рефакторинг, чтобы избежать тупиков?
3 ответа
Вложенные блокировки будут работать - однако одна из опасностей заключается в том, что нужно всегда блокировать объекты в одном и том же порядке, иначе может возникнуть тупик.
РЕДАКТИРОВАТЬ: Чтобы ответить на второй вопрос вокруг попытки заставить правильный порядок замков:
Возможное решение, чтобы избежать этого, может заключаться в том, чтобы заключить блокировку в общий метод блокировки, например так:
public void LockAndDoWork(Action action)
{
lock(lockObject1)
{
lock(lockObject2)
{
action();
}
}
}
Это может быть использовано следующим образом:
Thread1: LockAndDoWork(() => {do some work....});
Thread2: LockAndDoWork(() => {do some other work...});
Это может помочь избежать этой потенциальной проблемы - это особенно полезно, если можно ограничить видимость этих объектов из клиентского кода
Возможно, я должен спросить, как можно рефакторинг, чтобы избежать тупиков?
Определение всех синхронизирующих блокировок в строгом порядке приоритета и всегда приоритет наивысшего приоритета.
Это сложно: когда один блок кода, содержащий блокировку с более низким приоритетом, может вызвать вспомогательный код, который должен иметь блокировку с более высоким приоритетом, потребуется значительный рефакторинг.
Это можно сделать, но вы должны рассмотреть, что произойдет, если 2 потока, выполняющие этот код, попытаются получить обе блокировки одновременно - например, если поток 1 имеет блокировку для объекта 1, а поток 2 имеет блокировку для объекта 2? Кий тупик.
Кто-то лучше меня может дать вам пример кода, который должен быть безопасным:)