Re[4]: Проект утилитной библиотечки
От: nigh  
Дата: 17.03.16 20:45
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Здравствуйте, nigh, Вы писали:


N>>Это, вроде отцы-основатели не рекомендуют делать. Они даже не рекмендуют больше lock использовать https://blogs.msdn.microsoft.com/ericlippert/2009/03/06/locks-and-exceptions-do-not-mix/


AVK>Ну, если судить по твоей ссылке, то "не рекомендуют" сильно сказано. Кроме того, в случае с RWLock это не борьба с исключением, а просто способ указать в коде scope, в котором лок действует. Примерно как Html.BeginForm в MVC.


Да нет, там все гораздо глубже. Основная мысль в том, что Disposable и try-finally для семантики локов не подходят и создают ложное ощущение безопасности.
В случае с rwlock, если в процессе выполнения операции внутри using возникнет исключение, finally-блок радостно разблокирует заблокированный ресурс и вы получите букет с race conditions, unprecitable behavior и т. д. (т.е. unlock произойдет тогда, когда вы его не ожидали, а не должен был произойти в принципе)

Причем, самое ужасное, что такой дизайн кода получается неявно (в случае явного вызова lock / unlock и отсутствия implicit try/finally в глаза сразу бросаются вопросы "а что будет если тут будет exception?")



using(GetRWLock())
{
   UpdateJournal(AccountA, AccountB, 100)
   AddMoney(AccountA, 100)
   WithdrawMoney(AccountB, 100)    //throw an exception here, all other threads now receive an account in an incorrect state
}



var lc = GetRWLock();

lc.wlock();
UpdateJournal(AccountA, AccountB, 100)
AddMoney(AccountA, 100)
WithdrawMoney(AccountB, 100)    //throw an exception here, will never unlock unless proper recovery is done - likely a deadlock, but no further data corruption by other threads

rwlock.unlock();
Отредактировано 17.03.2016 20:48 nigh . Предыдущая версия .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.