Потоки в C# (критика)
Что именно тебя удивляет?
Что именно тебя удивляет?То, что я написал. Что этот код умирает с дедлоком.
Или тебя удивляет, что в одном случае стоит Wait(500 а в другом Wait(1000 а всё равно случается дедлок?
Можешь ещё написать финалайзер, в котором тоже что-нибудь залочЪ. Вот будет удивительно! Или ещё можно в финалайзерах выкидывать объект из очереди на удаление, тоже мазёвая штука.Блядь. Нет. Меня ничто не удивляет, но я считаю такое поведение серьёзной ошибкой проектирования языка и потоковых библиотек. Ты хотя бы посмотрел, ГДЕ и КАК повисают оба потока или пиздишь без дела, являясь любителем C#? Кстати, в Java подобный код не повиснет.
Или тебя удивляет, что в одном случае стоит Wait(500 а в другом Wait(1000 а всё равно случается дедлок?
Thread.Abort Method
Raises a ThreadAbortException in the thread on which it is invoked, to begin the process of terminating the thread. Calling this method usually terminates the thread.
...
The thread is not guaranteed to abort immediately, or at all. This situation can occur if a thread does an unbounded amount of computation in the finally blocks that are called as part of the abort procedure, thereby indefinitely delaying the abort.
...
If, while executing unmanaged code, a thread ignores a ThreadAbortException, the system re-throws the ThreadAbortException when the thread begins executing managed code.
Особенно внимательно стоит прочесть третий абзац.
Такое поведение не является "хорошим", но оно является документированным и таково "by design". В результате, Microsoft не рекомендует использовать Thread.Abort.
Когда ты вызываешь Abort, поток висит в lock, т.е. на самом деле в unmanaged codeДа, да, со всем этим разобрались. Документацию почитали. Пост только о том, что прерывание потоков сделано криво.
С потоками в .net и еще одна задница есть: если в потоке не из ThreadPool возникает неотловленное исключение, валится весь домен.
Пост только о том, что прерывание потоков сделано криво.
Оно везде сделано криво (имеется в виду насильственное прерывание типа Thread.Abort): и в posix, и в win32, наверное и в jav'е не без косяков. Очень сложно сделать это прямо, если вообще возможно. Вряд ли стоило рассчитывать, что .net будет являться исключением из правила.
и в jav'е не без косяковВ Java как раз без косяков.
try
{
чо-то делаем с файлом
}
finally
{
чо-то поделали,
закрываем файл
}
Поток начал абортиться, когда исполнение вошло в finally, но еще не дошло до закрытия файла. Вопрос: что будет с файлом? Он так и будет незакрыт?
GC вызовет finalize для соответствующего файлу объекта и там файл закроется?
время исполнения finalizer-а конечно недетерминировано, при наличии достаточного количества памяти это может произойти, скажем, через полчаса, да? что в это время будут делать другие желающие поюзать этот файл? есть предположение, что либо прибьют процесс, либо как-то специально ручками вызовут GC
Поток начал абортиться, когда исполнение вошло в finally, но еще не дошло до закрытия файла. Вопрос: что будет с файлом? Он так и будет незакрыт?Нет, всё будет в порядке. Поток прерывается, после чего исключение выкидывается только в ждущих функциях. Которые в finally на уровне языка заставят включить в try/catch блоки, т.к. они throws InterruptedException.
Или тут есть отличие между .net и Java? Если да, то можно подробно описать поведение программы при Abort-е Thread-а?
Отличие, наверное, в том, что InterruptedException может возникнуть не везде, а только в особых функциях, типа sleep/waitFor/...
Еще раз: у нас исполнялся finally, выбросился ThreadAbortedException (или как там аналог называется и мы пролетели мимо закрытия файла.
Или тут есть отличие между .net и Java? Если да, то можно подробно описать поведение программы при Abort-е Thread-а?
finally {
try {
actionsWhichThrowInterruptedException;
}
catch (InterruptedException e) {
}
file.close;
}
Видишь, тебе синтаксически не дадут просто так вызвать функции, которые викидывают InterruptedException. От тебя потребуют try/catch или спецификации исключения. Thread.interrupt просто ставит потоку флаг. После чего этот флаг можно либо проверить руками, либо вызов следующей ждущей функции сразу же кинет InterruptedException, либо уже выполняющаяся ждущая функция выкинет InterruptedException.
т.е. получается, что если у меня в потоке есть бесконечный цикл while (true) {}, который находится в функции без декларации возможности выброса InterruptedException, то поток никак нельзя будет убить?
т.е. получается, что если у меня в потоке есть бесконечный цикл while (true) {}, который находится в функции без декларации возможности выброса InterruptedException, то поток никак нельзя будет убить?Есть функции грубого останова, которые очень не рекомендуется использовать. Но я не вижу в отсутствии способа остановить такой поток ничего плохого.
о, это хорошо. Более удобно, чем в .net. Хотя, видимо к функции грубого останова все те же минусы, что и к .net-овскому Abort применимы.
Хотя, видимо к функции грубого останова все те же минусы, что и к .net-овскому Abort применимыКонечно, применимы. Но эти минусы очень плохие, хуже чем в C#.
Оставить комментарий
kokoc88
Вот такой код умирает в дедлоке: