Неявне блокування (шаблон проєктування) — Вікіпедія

Неявне блокування (англ. 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); 

Див. також[ред. | ред. код]

Джерела[ред. | ред. код]