ReaderWriterLockSlim problems
От: Аноним  
Дата: 13.12.13 12:40
Оценка: :))
Ознакомтесь, пожалуйста, с A story of orphaned ReaderWriterLockSlim и
ReaderWriterLockSlim fails on dual-socket environments.
Сразу предупреждаю — впечатлительным 21-летним сеньерам лучше это вообще не читать.

Вкратце:


Посему вопрос к сообществу: сталикивались ли вы с подобным поведением и подтверждаете ли тезисы, изложенные в статьях и здесь.

Вперед.
Re: ReaderWriterLockSlim problems
От: scale_tone Норвегия https://scale-tone.github.io/
Дата: 13.12.13 12:57
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Посему вопрос к сообществу: сталикивались ли вы с подобным поведением и подтверждаете ли тезисы, изложенные в статьях и здесь.


Сталкивались. Наблюдали большое число System.Threading.ReaderWriterCount в Gen2 под нагрузкой. Пока забили.
Re: ReaderWriterLockSlim problems
От: Аноним  
Дата: 14.12.13 14:40
Оценка: :)
Здравствуйте, Аноним, Вы писали:

Почему Lock нельзя просто поместить в блок Try

var lockIsHeld = false;
try {
   rwl.EnterReadLock();
   lockIsHeld = true;
   // Do work here
}
finally {
   if (lockIsHeld)
      rwl.ExitReadLock();
}
Re[2]: ReaderWriterLockSlim problems
От: Abyx Россия  
Дата: 14.12.13 15:10
Оценка: -1 :)
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Аноним, Вы писали:


А>Почему Lock нельзя просто поместить в блок Try


А>
А>var lockIsHeld = false;
А>try {
А>   rwl.EnterReadLock();
А>   lockIsHeld = true;
А>   // Do work here
А>}
А>finally {
А>   if (lockIsHeld)
А>      rwl.ExitReadLock();
А>}
А>


какая же гадость этот ваш сишарп)
In Zen We Trust
Re: ReaderWriterLockSlim problems
От: drol  
Дата: 14.12.13 21:16
Оценка: 22 (1)
Здравствуйте, Аноним, Вы писали:

А>ReaderWriterLockSlim имеет проблемы с грубыми прерываниями потоков


А кто их не имеет-то ??? Любой некооперативный механизм "прерывания" исполнения потока, в общем случае, портит разделяемое состояние.

А>ReaderWriterLockSlim имеет проблемы на серверных конфигурациях (>1 физического процессора)


Он их может и имеет, но вот анализ автора противоречит тому, что вижу лично я.

В декомпилированном ReSharper'ом коде ReaderWriterLockSlim, и с ExitMyLock(), и с инкрементом owners всё в порядке. В первом случае вызывается Volatile.Write(), а во втором все манипуляции выполняются внутри lock'а. Но код мутный. Есть куча внутренних setter'ов для owners, мне было лень смотреть все ли их вызовы внутри lock'ов.

Также у автора зело хитрое железо. Многопроцессорные штуки на семействе Xeon E5-2600 являются NUMA-системами. Согласно документации, там вроде всё должно быть когерентно, но запросто могут быть разложены какие-нибудь тонкие грабли.

А>Краткая переписка с Jeffrey Richter


А переписка-то где ??? Что-то не по глазам...
Re: ReaderWriterLockSlim problems
От: Sinix  
Дата: 15.12.13 11:35
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Посему вопрос к сообществу: сталикивались ли вы с подобным поведением и подтверждаете ли тезисы, изложенные в статьях и здесь.


Автор создал себе офигенные проблемы уже в момент использования thread.Abort(), всё остальное — уже последствия. Расписывать подробно особого смысла нет, достаточно оф. документации:

There is also a chance that a static constructor could be aborted. In rare cases, this might prevent instances of that class from being created in that application domain.

Если вас устраивают такие грабли в продакшне — то и всё остальное пугать не должно.

P.S. А на переписку с Рихтером я бы посмотрел
Re[2]: ReaderWriterLockSlim problems
От: Tom Россия http://www.RSDN.ru
Дата: 15.12.13 13:41
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, Аноним, Вы писали:


А>>Посему вопрос к сообществу: сталикивались ли вы с подобным поведением и подтверждаете ли тезисы, изложенные в статьях и здесь.


S>Автор создал себе офигенные проблемы уже в момент использования thread.Abort(), всё остальное — уже последствия. Расписывать подробно особого смысла нет, достаточно

Ээээ на этом месте по подробнее можно?
thread.Abort используется в куче мест самим фрейсворком.
Народная мудрось
всем все никому ничего(с).
Re[3]: ReaderWriterLockSlim problems
От: samius Япония http://sams-tricks.blogspot.com
Дата: 15.12.13 15:44
Оценка: 6 (1) +1
Здравствуйте, Tom, Вы писали:

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


S>>Автор создал себе офигенные проблемы уже в момент использования thread.Abort(), всё остальное — уже последствия. Расписывать подробно особого смысла нет, достаточно

Tom>Ээээ на этом месте по подробнее можно?
Tom>thread.Abort используется в куче мест самим фрейсворком.
Я бы не сказал что в куче

Thread.Abort used by
   System.Media.SoundPlayer.LoadSync()
   System.Media.SoundPlayer.SetupSoundLocation(string)
   System.Media.SoundPlayer.SetupStream(Stream)
   System.ServiceModel.ComIntegration.DllHostInitializeWorker.Startup(IProcessInitControl)
Thread.Abort(object) used by
   System.Web.HttpResponse.AbortCurrentThread()
   System.Web.RequestTimeoutManager.RequestTimeoutEntry.TimeoutIfNeeded(DateTime)

Возможно куча пролетела мимо, но в рефлекторе на момент анализа было порядка 20и сборок фреймворка.
Re[3]: ReaderWriterLockSlim problems
От: Sinix  
Дата: 16.12.13 05:18
Оценка: +2
Здравствуйте, Tom, Вы писали:

S>>Автор создал себе офигенные проблемы уже в момент использования thread.Abort(), всё остальное — уже последствия. Расписывать подробно особого смысла нет, достаточно

Tom>Ээээ на этом месте по подробнее можно?

Thread.Abort() — это метод отчаяния. Точно так же, как catch {}, он не решает исходную проблему, а маскирует её. Необходимость насильственного прерывания потока означает, что мы _уже_ не можем контролировать его выполнение, и, как следствие, не можем гарантировать корректность его состояния.

Если поток разделяет свой состояние с остальными потоками — всё ещё хуже: убийство потока может поломать всё приложение. Конечно, можно начать защищаться: добавлять cer, не вызывать "неустойчивые" методы из BCL, писать для всех выделяемых ресурсов финализаторы (например, чтобы если что, освободить "утёкшую" блокировку) etc. По сути, мы получим более продвинутый API для всё той же проблемы — прерывания выполнения в любой точке приложения. Разумеется, со своими тараканами: непредсказуемым порядком освобождения ресурсов, повышенной нагрузкой на финализатор, и, главное, с нерешённой исходной проблемой — см. пример с static-конструкторами из документации. Их-то никак не защитишь

Для более-менее свежего кода, который по полной использует task/await (да даже threadpool), Thread.Abort является чистой диверсией. С учётом штатного CancellationToken — ещё и ненужной.

Tom>thread.Abort используется в куче мест самим фрейсворком.

samius написал выше — всего в паре мест И то, как минимум в SoundPlayer от Abort() точно можно избавиться.
Re[4]: ReaderWriterLockSlim problems
От: Tom Россия http://www.RSDN.ru
Дата: 16.12.13 12:59
Оценка: -3
Здравствуйте, Sinix, Вы писали:

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


S>>>Автор создал себе офигенные проблемы уже в момент использования thread.Abort(), всё остальное — уже последствия. Расписывать подробно особого смысла нет, достаточно

Tom>>Ээээ на этом месте по подробнее можно?

S>Thread.Abort() — это метод отчаяния. Точно так же, как catch {}, он не решает исходную проблему, а маскирует её.

Это с кокого такого перепугу такое делается заявление?
Отчаяние это TerminateThread а Thread.Abort это более чем кошерное решение проблемы с закрытием и освобождение ресурсов.

S>Необходимость насильственного прерывания потока означает, что мы _уже_ не можем контролировать его выполнение, и, как следствие, не можем гарантировать корректность его состояния.

А с чего ты взял что ты вообще поток контролировал.
Представь себя на месте II&ASP.NET или того же WCF.
Например: Случился таймаут выполнения метода WCF. Вопрос, что делать.
Оставлсять всё так как и есть, т.е. продолжить методу висесть или попытаться его заабортить...?

Или другой случай, случился ресайклинг у IIS App Pool-а, опять же что делать с зависшими запросами....
Народная мудрось
всем все никому ничего(с).
Re[4]: ReaderWriterLockSlim problems
От: Tom Россия http://www.RSDN.ru
Дата: 16.12.13 13:07
Оценка:
Здравствуйте, samius, Вы писали:

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


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


S>>>Автор создал себе офигенные проблемы уже в момент использования thread.Abort(), всё остальное — уже последствия. Расписывать подробно особого смысла нет, достаточно

Tom>>Ээээ на этом месте по подробнее можно?
Tom>>thread.Abort используется в куче мест самим фрейсворком.
S>Я бы не сказал что в куче
А что код фрефмворка обязан вызывать Thread.Abort что бы заабортить поток?
Народная мудрось
всем все никому ничего(с).
Re[5]: ReaderWriterLockSlim problems
От: samius Япония http://sams-tricks.blogspot.com
Дата: 16.12.13 13:34
Оценка:
Здравствуйте, Tom, Вы писали:

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


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


Tom>>>thread.Abort используется в куче мест самим фрейсворком.

S>>Я бы не сказал что в куче
Tom>А что код фрефмворка обязан вызывать Thread.Abort что бы заабортить поток?
Вообще говоря, не обязан. Но я опровергал ваше утверждение о том что thread.Abort используется в куче мест самим фреймворком.
Re[5]: ReaderWriterLockSlim problems
От: samius Япония http://sams-tricks.blogspot.com
Дата: 16.12.13 13:39
Оценка: 22 (1) +2
Здравствуйте, Tom, Вы писали:

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


Tom>А что код фрефмворка обязан вызывать Thread.Abort что бы заабортить поток?

Не знаю, что код фреймворка вызывает что бы заабортить поток, но вот мнение Липперта относительно Abort-а

In short, Thread.Abort is at best indicative of bad design, possibly unreliable, and extremely dangerous. It should be avoided at all costs; the only time you should ever even consider aborting a thread is in some sort of "emergency shutdown" code where you are attempting to tear down an appdomain as cleanly as possible.

и еще

>Are there any other posibility to terminate threads?

Yes. Your problem is that you should never start up a thread that you cannot tell politely to stop, and it stops in a timely manner. If you are in a situation where you have to start up a thread that might be (1) hard to stop, (2) buggy, or worst of all (3) hostile to the user, then the right thing to do is to make a new process, start the thread in the new process, and then terminate the process when you want the thread to go down. The only thing that can guarantee safe termination of an uncooperative thread is the operating system taking down its entire process.

Полагаю что все-таки фреймворк не так часто абортит потоки, как вам хочется.
Re[5]: ReaderWriterLockSlim problems
От: Sinix  
Дата: 16.12.13 13:48
Оценка: 71 (4)
Здравствуйте, Tom, Вы писали:

Tom>Это с кокого такого перепугу такое делается заявление?

Ок, а как ещё назвать решение прерывать поток выполнения в произвольном месте?

Tom>Отчаяние это TerminateThread а Thread.Abort это более чем кошерное решение проблемы с закрытием и освобождение ресурсов.

Как раз с "кошерным" освобождением ресурсов _в общем случае_ у Thread.Abort большие проблемы. Первые же ссылки из гугла
http://stackoverflow.com/questions/710070/timeout-pattern-how-bad-is-thread-abort-really
http://joeduffyblog.com/2009/03/13/managed-code-and-asynchronous-exception-hardening/
http://stackoverflow.com/questions/6382997/is-using-thread-abort-and-handling-threadabortexception-in-net-safe-practice
http://geekswithblogs.net/akraus1/archive/2012/10/22/151047.aspx
http://onoffswitch.net/when-to-abort-a-thread/

Tom>Например: Случился таймаут выполнения метода WCF. Вопрос, что делать.

Tom>Оставлсять всё так как и есть, т.е. продолжить методу висесть или попытаться его заабортить...?
Во-первых, поток не является единицей изоляции. Прибивать надо AppDomain/хост-процесс.
Во-вторых, в твоих сценариях не предполагается продолжение работы остальных (зависящих от текущего) потоков. У автора исходной статьи такая надежда была
Ну, и в-третьих, твои сценарии предполагают чистые (утилитарные) потоки без разделяемого состояния. ReaderWriterLockSlim намекает на полностью противоположное.
Re[2]: ReaderWriterLockSlim problems
От: Аноним  
Дата: 16.12.13 13:50
Оценка:
Здравствуйте, drol, Вы писали:

D>Здравствуйте, Аноним, Вы писали:


А>>ReaderWriterLockSlim имеет проблемы с грубыми прерываниями потоков


D>А кто их не имеет-то ??? Любой некооперативный механизм "прерывания" исполнения потока, в общем случае, портит разделяемое состояние.


А>>ReaderWriterLockSlim имеет проблемы на серверных конфигурациях (>1 физического процессора)


D>Он их может и имеет, но вот анализ автора противоречит тому, что вижу лично я.


D>В декомпилированном ReSharper'ом коде ReaderWriterLockSlim, и с ExitMyLock(), и с инкрементом owners всё в порядке. В первом случае вызывается Volatile.Write(), а во втором все манипуляции выполняются внутри lock'а. Но код мутный. Есть куча внутренних setter'ов для owners, мне было лень смотреть все ли их вызовы внутри lock'ов.


Код я смотрел здесь:
http://referencesource.microsoft.com/netframework.aspx Net 4.5Update1 View EULA Download


0:022> !DumpIL 000007fbf85a8000
ilAddr = 000007fbf88c7b5f
IL_0000: ldarg.0 
IL_0001: ldc.i4.0 
IL_0002: stfld System.Threading.ReaderWriterLockSlim::myLock
IL_0007: ret


В каком здесь месте нарисовался Volatile.Write? Передавайте привет декомпилерам, они такие классные, особенно бесплатные.


D>Также у автора зело хитрое железо. Многопроцессорные штуки на семействе Xeon E5-2600 являются NUMA-системами. Согласно документации, там вроде всё должно быть когерентно, но запросто могут быть разложены какие-нибудь тонкие грабли.

Там не NUMA, там мало памяти (всего 16 Гб).

А>>Краткая переписка с Jeffrey Richter


D>А переписка-то где ??? Что-то не по глазам...

Ничего полезного. Рихтер предлагает свою библиотеку, она не рабочая.
Re[6]: ReaderWriterLockSlim problems
От: Аноним  
Дата: 16.12.13 14:01
Оценка:
Здравствуйте, Sinix, Вы писали:

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


Tom>>Это с кокого такого перепугу такое делается заявление?

S>Ок, а как ещё назвать решение прерывать поток выполнения в произвольном месте?
Не в произвольном месте, читайте ниже.

Tom>>Отчаяние это TerminateThread а Thread.Abort это более чем кошерное решение проблемы с закрытием и освобождение ресурсов.

S>Как раз с "кошерным" освобождением ресурсов _в общем случае_ у Thread.Abort большие проблемы. Первые же ссылки из гугла
S>http://stackoverflow.com/questions/710070/timeout-pattern-how-bad-is-thread-abort-really
S>http://joeduffyblog.com/2009/03/13/managed-code-and-asynchronous-exception-hardening/
S>http://stackoverflow.com/questions/6382997/is-using-thread-abort-and-handling-threadabortexception-in-net-safe-practice
S>http://geekswithblogs.net/akraus1/archive/2012/10/22/151047.aspx
S>http://onoffswitch.net/when-to-abort-a-thread/
Проблемы у тех, кто не знает как работает Thread.Abort и как уберечь ресурсы от пагубных последствий. А мистер Joe Duffy — вообще автор ReaderWriterLockSlim, на словах — Лев Толстой, а на деле — сами знаете.
Вопреки вопросам от 21-летних сеньеров и ответам от людей сравнимой квалификации, Thread.Abort содержит сложную логику и не прерывает поток где попало. Более того, код можно написать так, чтобы исключить нужные регионы от прерываний.

Контейнеры приложений без абортов вообще сложно представить.

Tom>>Например: Случился таймаут выполнения метода WCF. Вопрос, что делать.

Tom>>Оставлсять всё так как и есть, т.е. продолжить методу висесть или попытаться его заабортить...?
S>Во-первых, поток не является единицей изоляции. Прибивать надо AppDomain/хост-процесс.
S>Во-вторых, в твоих сценариях не предполагается продолжение работы остальных (зависящих от текущего) потоков. У автора исходной статьи такая надежда была
S>Ну, и в-третьих, твои сценарии предполагают чистые (утилитарные) потоки без разделяемого состояния. ReaderWriterLockSlim намекает на полностью противоположное.
Re[5]: ReaderWriterLockSlim problems
От: SergeyT. США http://sergeyteplyakov.blogspot.com/
Дата: 16.12.13 14:01
Оценка: 17 (2) +3
Здравствуйте, Tom, Вы писали:

S>>>>Автор создал себе офигенные проблемы уже в момент использования thread.Abort(), всё остальное — уже последствия. Расписывать подробно особого смысла нет, достаточно

Tom>>>Ээээ на этом месте по подробнее можно?

S>>Thread.Abort() — это метод отчаяния. Точно так же, как catch {}, он не решает исходную проблему, а маскирует её.

Tom>Это с кокого такого перепугу такое делается заявление?
Tom>Отчаяние это TerminateThread а Thread.Abort это более чем кошерное решение проблемы с закрытием и освобождение ресурсов.

Разница меджу TerminateThread и Thread.Abort в том, что первый гарантированно приведет к проблемам, а второй — лишь в некоторых случаях.

Проблема в том, что Thread.Abort может прервать исполнение практически любой управляемой инструкции, а это значит, что без хитрых хитростей мы можем захватить ресурс, но не спеть сохранить на него хэндл в переменной. Есть ли вообще уверенность, что в случае вызова Thread.Abort будут корректно освобождаться ресурсы в блоке using? Нет, таких гарантий нет, поскольку обеспечить их очень сложно, а проверить — еще сложнее.

Помимо приведенных ссылок, вот тут тоже можно чутка подробнее об этом почитать: О вреде вызова Thread.Abort.


Tom>Или другой случай, случился ресайклинг у IIS App Pool-а, опять же что делать с зависшими запросами....

Когда мы точно знаем, что за код исполняется потоком, то все ОК, но в *общем случае* гарантировать корректное состояние программы после Thread.Abort нельзя.
Re[6]: ReaderWriterLockSlim problems
От: Tom Россия http://www.RSDN.ru
Дата: 16.12.13 14:19
Оценка: -4
Здравствуйте, Sinix, Вы писали:

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


Tom>>Это с кокого такого перепугу такое делается заявление?

S>Ок, а как ещё назвать решение прерывать поток выполнения в произвольном месте?
Как угодно. Если это операция безопасна то не вижу проблем. С ThreadAbort и нормальными руками это вполне безопасно.

Tom>>Отчаяние это TerminateThread а Thread.Abort это более чем кошерное решение проблемы с закрытием и освобождение ресурсов.

S>Как раз с "кошерным" освобождением ресурсов _в общем случае_ у Thread.Abort большие проблемы. Первые же ссылки из гугла
Это конечно круто взять ссылки из гугла и кинуть их сюда.
Это конечно же доказывает многое...
Проблемы с ThreadAbort у людей бывают когда они не понимают что это такое, когда выбрасывается и что с ним вообще делать надо.
Это мне напоминает мнение когда люди считают проблемой — любое исключение не понимая что исключение это просто механизм, инструмент в их руках.
Причём этим инструментом можно себе дырку в ноге прокалупать или можно построить что то хорошее...

Tom>>Например: Случился таймаут выполнения метода WCF. Вопрос, что делать.

Tom>>Оставлсять всё так как и есть, т.е. продолжить методу висесть или попытаться его заабортить...?
S>Во-первых, поток не является единицей изоляции. Прибивать надо AppDomain/хост-процесс.
Очень интересно. Т.е. если у меня таймаут при вызове веб сервиса мне надо домен прибить?
Или ещё круче аж процесс? Может проще винду перегрузить или даже диск отформатировать...

S>Во-вторых, в твоих сценариях не предполагается продолжение работы остальных (зависящих от текущего) потоков. У автора исходной статьи такая надежда была

S>Ну, и в-третьих, твои сценарии предполагают чистые (утилитарные) потоки без разделяемого состояния.
Ээээ, опять же с какого перепугу???
Народная мудрось
всем все никому ничего(с).
Re[6]: ReaderWriterLockSlim problems
От: Tom Россия http://www.RSDN.ru
Дата: 16.12.13 14:21
Оценка: -1
Здравствуйте, samius, Вы писали:

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


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


Tom>>А что код фрефмворка обязан вызывать Thread.Abort что бы заабортить поток?

S>Не знаю, что код фреймворка вызывает что бы заабортить поток, но вот мнение Липперта относительно Abort-а
S>
S>In short, Thread.Abort is at best indicative of bad design, possibly unreliable, and extremely dangerous. It should be avoided at all costs; the only time you should ever even consider aborting a thread is in some sort of "emergency shutdown" code where you are attempting to tear down an appdomain as cleanly as possible.

Вы будете удивлены но я абсолютно с ним согласен. Что абсолютно не значит что ThreadAbort зло во всех случаях.
Есть целый класс случаев когда без него просто невозможно обойтись. Это случаи когда вы не владеете кодом который выполняется в вашем потоке в данную минуту.
Примеры ASP.NET, WCF, SQL Server & CLR.
Во всех этих примерах применяется ThreadAbort
Народная мудрось
всем все никому ничего(с).
Re[6]: ReaderWriterLockSlim problems
От: Tom Россия http://www.RSDN.ru
Дата: 16.12.13 14:28
Оценка: -1
ST>Разница меджу TerminateThread и Thread.Abort в том, что первый гарантированно приведет к проблемам, а второй — лишь в некоторых случаях.
Разница там как между взрывом атомной бомбы и игрой детей с зажигалкой
дети с зажигалкой конечно могут проблем наделать но только если они дети несмышлёные.

ST>Проблема в том, что Thread.Abort может прервать исполнение практически любой управляемой инструкции, а это значит, что без хитрых хитростей мы можем захватить ресурс, но не спеть сохранить на него хэндл в переменной.

В чём проблема сохранить в переменной а потом захватить ресурс?

ST>Есть ли вообще уверенность, что в случае вызова Thread.Abort будут корректно освобождаться ресурсы в блоке using? Нет, таких гарантий нет, поскольку обеспечить их очень сложно, а проверить — еще сложнее.

Если желание и понимание есть то сделать можно. Если понимания нет то проблемы с юзингом можно получить и без abort-а. Элементарный случай — исключение в конструкторе.

ST>Помимо приведенных ссылок, вот тут тоже можно чутка подробнее об этом почитать: О вреде вызова Thread.Abort.

Сергей я вкурсе твоего блога

Tom>>Или другой случай, случился ресайклинг у IIS App Pool-а, опять же что делать с зависшими запросами....

ST>Когда мы точно знаем, что за код исполняется потоком, то все ОК, но в *общем случае* гарантировать корректное состояние программы после Thread.Abort нельзя.
Я об этом и говорю, нельзя взять и агульно назвать Thread.Abort злом.
Те кто понимает насколько огромный это шаг по сравнению с TerminateThread особенно это понимают.
Ну и как я уже говорил ранее есть случаи где без Thread.Abort невозможно обойтись в принципе.
Народная мудрось
всем все никому ничего(с).
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.