Неявне блокування (шаблон проєктування)
Неявне блокування (англ. Implicit Lock) — шаблон проєктування, який пропонує винести блокування на глобальний рівень.
Будь-яка схема блокування корисна лише в тому випадку, якщо в ній не зроблено "проколів". Якщо забути накласти блокування, тоді вся схема блокування є марною. Якщо забути звільнити ресурс, він буде заблокований, що приведе до погіршення продуктивності аплікації. Застосування блокування запису, замість блокування читання призведе до використання застарілих даних, а невірне використання версії — до небажаних змін даних іншим користувачем. Окрім цього, механізм паралельного доступу важко тестувати через, що помилки в блокуванні можуть бути не замічені в тестах.
Щоб уникнути помилок розробників під час накладання блокування, даний шаблон пропонує винести блокування на глобальний рівень. Таким чином, можна один раз описати логіку блокування, яка буде застосовуватись до усіх транзакцій у системі (чи лише до необхідних), або ж скористатись вбудованим механізмом, що пропонує фреймворк.
Реалізуємо неявне блокування за допомогою декораторів. Головна їх перевага, в тому, що об'єкт до яких вони застосовуються навіть не підозрює про зміни у своїй функціональності.
interface IUserRepository
{
User GetUser(int id);
}
class UserRepository : IUserRepository
{
public User GetUser(int id)
{
return db.Users.Find(id);
}
}
class ConcurrentUserRepository : IUserRepository
{
public User GetUser(int id)
{
// оскільки в межах сеансу може відбуватись пошук одного і того самого об'єкту декілька разів
// перевіряємо чи у сеансу вже є блокування на даний ресурс
LockKey lockKey = LockKey.Build(_appSessionManager.GetSessionId(), id.ToString());
_lockService.AcquireLock(lockKey);
try
{
return _userRepository.GetUser(id);
}
finally
{
_lockService.ReleaseLock(lockKey);
}
}
}
Тоді при використанні сервісу ми не задумуватимемось про блокування.
var userRepository = new ConcurrentUserRepository(new UserRepository());
// ресурс неявно блокується
var user = userRepository.GetUser(19);
- Implicit Lock [Архівовано 26 листопада 2020 у Wayback Machine.]