Здравствуйте, Maxim S. Shatskih, Вы писали:
D>>Тем не менее, обнаружить дедлок и разрешить его -- это конечно хорошо. Но это не решает >>проблему. Дедлоки никуда не деваются
MSS>Правильно написанный код вообще не создает дедлоков.
Абсолютно согласен. Только хитрая реализация mutex'ов не делает этот код более правильным.
>>возникать при синхронизации потоков не только mutex'ами, а и любыми другими механизмами >>синхронизации,
MSS>В рамках нашей дискуссии слово mutex есть синоним слова lock и означает любой примитив синхронизации — хоть ERESOURCE, хоть "synchronized" в яве.
Понятно. На мой взгляд под синхронизацией потоков следует понимать не только защиту данных от одновременного доступа к ним, но и оповещение одного потока другим о каком-то событии. Например, когда один поток ожидает готовности данных, подготавливаемыми для него другими потоками. Здесь только локами не обойтись. И зависание потока на условной переменной, которую никто никогда не дергнет, я также склонен называть дедлоком.
>>частности, с семафорами дедлоки не обнаруживаются (просто потому, что залочить его может >>один поток, а разлочить другой, может быть даже тот, который еще и не запущен)
MSS>За 7 с лишним лет системного программирования ни разу не возникала нужда в семафоре почему-то
Здравствуйте, eao197, Вы писали:
E>Кстати, не понятно, зачем им потребовалось новый язык создавать (для Ph.D что ли?), при существовании-то Erlang-а?
Возможно. Одно дело промышленный язык, другое дело исследовательский. Его проще менять, плюс компилятор/ВМ можно писать на том, что знаеш, а не на том, что выбрали авторы исходной системы.
E>Более того, асинхронное взаимодействие можно и в существующие языки добавлять (которые изначально таких возможностей не содержали).
Как я помню, основная фича там не асинхронность, а capability-based security.
Здравствуйте, Andrei N.Sobchuck, Вы писали:
ANS>Возможно. Одно дело промышленный язык, другое дело исследовательский. Его проще менять, плюс компилятор/ВМ можно писать на том, что знаеш, а не на том, что выбрали авторы исходной системы.
Если речь идет только об исследовательском проекте -- тогда понятно.
E>>Более того, асинхронное взаимодействие можно и в существующие языки добавлять (которые изначально таких возможностей не содержали).
ANS>Как я помню, основная фича там не асинхронность, а capability-based security.
Об этом уже времени не было читать
Да и тема топика предполагала обсуждение только дедлоков
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
D>Понятно. На мой взгляд под синхронизацией потоков следует понимать не только защиту данных от одновременного доступа к ним, но и оповещение одного потока другим о каком-то событии.
Да. Согласен.
>Например, когда один поток ожидает готовности данных, подготавливаемыми для него другими потоками. Здесь только локами не обойтись. И зависание потока на условной переменной, которую никто никогда не дергнет, я также склонен называть дедлоком.
Конечно. Очень часто такое бывает от неправильного сочетания ожидания и мутекса. Ожидание под мутексом, например.
Инструментировать код, чтобы этого не было, невозможно (blocking может быть очень много кто, read(), например), но выработать правила, предотвращающие это — можно.
D>Ok. Как насчет condvar или event?
Event, конечно. Condvar лично мне кажется противоестественным. Грубо говоря, светофор или красный, или зеленый. А светофор, который может мигнуть зеленым так, что только ныне стоящие машины это увидят и тронутся (а те, кто приехал позже на долю секунды, уже остановятся) — какое-то извращение.
Нелогичный это объект. На коленке сляпанный и хреновый. Единственный с него толк — экономия kernel memory. Все. Неактуально сейчас.
И нет никакого функционала, никакого поведенческого паттерна, который можно было бы реализовать на condvarах и нельзя на эвентах.
Кстати, в ядре линукса я кондваров не видел, а вот эвенты вполне даже есть — wait queues.
E>Кстати, не понятно, зачем им потребовалось новый язык создавать (для Ph.D что ли?), при существовании-то Erlang-а? Более того, асинхронное
Один нюанс. Для создания языка, который гарантирует отсутствие дедлоков на уровне синтаксиса, придется завести ключевое (или атрибут) слово blocking, разрешить помечать им функции и пометить целую кучу функций стандартной библиотеки — типа recv(), например — этим словом.
Иначе это все игрушки. Запросто можно дедлокнуться в recv(), если позвать его из-под мутекса.
Здравствуйте, Maxim S. Shatskih, Вы писали:
D>>Ok. Как насчет condvar или event?
MSS>Event, конечно. Condvar лично мне кажется противоестественным. Грубо говоря, светофор или красный, или зеленый. А светофор, который может мигнуть зеленым так, что только ныне стоящие машины это увидят и тронутся (а те, кто приехал позже на долю секунды, уже остановятся) — какое-то извращение.
MSS>Нелогичный это объект. На коленке сляпанный и хреновый.
Полагаю, что ты просто не нашел ему адекватной аналогии.
Представь стадион и бегунов, которые должны пробежать вокруг него ровно один круг. Изначально бегуны стоят на старте и ждут выстрела стартового пистолета. После выстрела (pthread_condvar_broadcast, PulseEvent, java.lang.Object.notifyAll) бегуны (потоки) пробегают круг и останавливаются на стартовой позиции. Если же стартовый пистолет заменить семафором и в момент старта включить зеленый свет на некоторое время и потом вернуть красный, то существует риск того, что одни бегуны успеют пробежать несколько кругов (до того как семафор станет красным), в то время как другие не успеют тронуться с места.
D>Представь стадион и бегунов, которые должны пробежать вокруг него ровно один круг.
Часто такой паттерн бывает? я имею в виду "ровно один круг"?
>кругов (до того как семафор станет красным), в то время как другие не успеют тронуться с >места.
Чаще встречается иной паттерн. Не бегуна, а курьера. Курьер получает свой груз — и мчится доставлять. Потом возвращается, получает следующий груз и вперед.
Это один из двух главнейших паттернов в многонитевом программировании. Второй — "туалетная кабинка", ну или рамка досмотра в аэропорту. Туда нельзя входить вдвоем. Следущий должен дождаться, когда предыдущий окончит свои дела. Это мутекс.
Дальше. Грузы хранятся в ожидании курьеров у стартовой линии. Когда грузы есть — горит зеленый, бери груз и беги. Когда нет — горит красный. Стой, ожидая груза.
Ну и как тут поможет стартовый пистолет? а если груз пришел, а курьеров на стартовой линии — нуль? из пистолета палить? а тогда курьер придет, а выстрел уже отгремел, и курьер замер навсегда. Еще раз из пистолета палить? а кто это будет делать, и как?
Здравствуйте, Maxim S. Shatskih, Вы писали:
D>>Представь стадион и бегунов, которые должны пробежать вокруг него ровно один круг.
MSS>Часто такой паттерн бывает? я имею в виду "ровно один круг"?
Ну, бывает раз есть. Такая вещь как monitor (mutex + condvar) встроена в платформы .NET и Java.
MSS>Чаще встречается иной паттерн. Не бегуна, а курьера. Курьер получает свой груз — и мчится доставлять. Потом возвращается, получает следующий груз и вперед.
MSS>Это один из двух главнейших паттернов в многонитевом программировании. Второй — "туалетная кабинка", ну или рамка досмотра в аэропорту. Туда нельзя входить вдвоем. Следущий должен дождаться, когда предыдущий окончит свои дела. Это мутекс.
MSS>Дальше. Грузы хранятся в ожидании курьеров у стартовой линии. Когда грузы есть — горит зеленый, бери груз и беги. Когда нет — горит красный. Стой, ожидая груза.
MSS>Ну и как тут поможет стартовый пистолет? а если груз пришел, а курьеров на стартовой линии — нуль? из пистолета палить? а тогда курьер придет, а выстрел уже отгремел, и курьер замер навсегда. Еще раз из пистолета палить? а кто это будет делать, и как?
Ну во-первых, по-моему, это совершенно естественно, что одни задачи хорошо решаются одними средствами, а другие -- другими. Поэтому, если что-то не решается или решается плохо одним средством (condvar'ом, например) или такие задачи встречаются редко -- это не повод он него отказываться. Ведь могут быть задачи, которые именно этим средством будут решаться лучше, чем любыми другими.
Во-вторых, что касается приведенной задачи про курьера, то по-моему, она прекрасно решается condvar'ом.
Курьер возвращается за грузом, он входит в критическую секцию и проверяет есть ли груз, который необходимо отнести. Если есть, то он его берет, выходит из критической секции и относит куда нужно. Если же груза нет, то он засыпает (освобождая на время сна критическую секцию, которую он занял). Когда выходит грузчик и выносит груз для курьера, он заходит в критическую секцию, ставит груз и будит одного (или всех) спящих курьеров (пистолетом или еще как), выходит из критической секции и идет за другим грузом. Если спящих курьеров нет, то он просто выходит. Проснувшиеся курьеры обратно занимают критическую секцию, проверяют наличие груза, берут его и уносят (освободив напоследок критическую секцию).
Здравствуйте, Maxim S. Shatskih, Вы писали:
MSS>Перед захватом мутекса смотрится, кто именно им владеет, и обходится дерево по этим указателям. Если в дереве обнаруживается цикл (т.е. если оно на самом деле не дерево) — то возникает exception, который возвращается callerу — или как код ошибки, или через try/catch — механизмы реализации exceptions тут не важны.
Глупые мутексы в дедлоке приводят к зависанию, а умные — к отказу от обслуживания. Это, конечно, лучше, но ненамного.
Представь себе: один поток такой
lock(mutex1);
...
while(!ok)
{
try
{
...
lock(mutex2); ... unlock(mutex2); // где-то в недрах есть охраняемый код
...
// мы во что бы то ни стало хотим пройти контрольный пункт
ok = true;
}
catch(...) {}
}
...
unlock(mutex1);
а второй — примерно симметричный ему. И они будут долбиться в DoS пока не надоест.
С глупыми мутексами тот же эффект можно получить, указывая таймауты.