none
Потоковые конфликты RRS feed

  • Вопрос

  • В дополнение к http://social.msdn.microsoft.com/Forums/ru-RU/programminglanguageru/thread/d75f6345-4c4b-4459-a2df-5f5eb77eae81

    Всем привет!

    В программе реализовано дерево потоков -
    Главный поток,
    ассинхронный API-прием сообщений,
    ассинхронная обработка этих сообщений с ассинхронной индикацией в отдельной форме,
    ассинхронное сохранение этих сообщений в текстовом файле на диске ...
    Примерно так.
    Скорость поступления ~ 1000 сообщений в секунду, 1 сообщение - это 50-80 байт.
    Программа способна обрабатывать гораздо быстрее - 10-15 тысяч сообщений в секунду.
    Программа висит в облаке, конект - 2 Gbps.

    Проблема.

    Периодически, относительно нечасто, ~ 1 раз в 2 недели, возникает загадочный конфликт -
    Безо всяких видимых причин резко снижается скорость приема сообщений и 
    плавно увеличивается задержка в сети,
    т.е. сначала это 1-2 секунды, потом 3, потом 5, и т.д. до бесконечности - пока программу не снимешь.
    Но при повторном запуске программы все начинает работать чисто и просто, как и должно быть.
    Ребята на том конце клянутся, что у них все ровно, что это все мое.
    Есть предположение, что, возможно, я имею дело с конфликтами в моих многочисленных потоках.

    Вопрос.

    Есть ли возможность как-то отлавливать конфликты в потоках?

    Пресловутый try-catch не помогает, как я уже говорил в предыдущем топике, 
    на который я сослался в начале этого поста.


    • Изменено QazRdx 26 марта 2013 г. 3:47
    26 марта 2013 г. 3:36

Ответы

  • Добрый день.

    У вас, судя по ошибке из предыдущего поста, проблема с Deadlock-ами. Решить ее не видя вашего кода скорее всего не получится, но могу рассказать на что обратить внимание.

    Итак, у вас блокируются для многопоточного доступа 2 и более ресурсов. Допустим два ресурса A и B. Первый поток их блокирует в порядке A, B. Второй в порядке B, A. В этом случае, если первый поток заблокировал A, а второй к этому моменту уже заблокировал B, то оба потока и попадают в клинч ожидая B и A, соответственно.

    Как решать такие проблемы:

    1. Блокировать все ресурсы во всей программе в одном и том же порядке. Т.е. вы разрабатываете перечень всех блокируемых ресурсов и упорядочив его блокируете в соответствии с этим порядком.

    2. Вы не просто пытаетесь захватить блокируемый ресурс, а пытаетесь его захватить в течении некоторого временного интервала (желательно случайного). Если вышли по таймауту, то освобождаете все захваченные ресурсы, ждете случайный по длительности интервал времени и снова пытаетесь все захватить.

    Как то так...


    26 марта 2013 г. 3:51
    Отвечающий

Все ответы

  • Добрый день.

    У вас, судя по ошибке из предыдущего поста, проблема с Deadlock-ами. Решить ее не видя вашего кода скорее всего не получится, но могу рассказать на что обратить внимание.

    Итак, у вас блокируются для многопоточного доступа 2 и более ресурсов. Допустим два ресурса A и B. Первый поток их блокирует в порядке A, B. Второй в порядке B, A. В этом случае, если первый поток заблокировал A, а второй к этому моменту уже заблокировал B, то оба потока и попадают в клинч ожидая B и A, соответственно.

    Как решать такие проблемы:

    1. Блокировать все ресурсы во всей программе в одном и том же порядке. Т.е. вы разрабатываете перечень всех блокируемых ресурсов и упорядочив его блокируете в соответствии с этим порядком.

    2. Вы не просто пытаетесь захватить блокируемый ресурс, а пытаетесь его захватить в течении некоторого временного интервала (желательно случайного). Если вышли по таймауту, то освобождаете все захваченные ресурсы, ждете случайный по длительности интервал времени и снова пытаетесь все захватить.

    Как то так...


    26 марта 2013 г. 3:51
    Отвечающий
  • Спасибо, Алексей!
    Надо подумать.
    26 марта 2013 г. 4:01
  • Честно говоря, не могу представить себе описанную Вами ситуацию,
    при которой два потока взаимно блокируются.
    Т.е. предполагается, что они одновременно обращаются друг к другу.
    Иначе - это ветви одного дерева, сросшиеся своими листьями.
    Можно, конечно, программировать и так, но, согласитесь, это нонсенс.

    Другое дело, если две или более ветки одновременно обращаются к одному и тому же ресурсу,
    например, к модулю, распечатывающему что-либо на одной и той же форме.
    Для этого конфликта существует замечательный в своей простоте Semafore,
    разруливающий потоки, конкурирующие за доступ к общему ресурсу.
    У меня, похоже, именно это и происходит...

    Велики и чудны дела твои...
    О, Майкрософт!

    30 марта 2013 г. 23:37
  • Проблемы с одновременным доступом к одному и тому же ресурсу, это действительно проблема решаемая при помощи симафоров и других объектов синхронизации. Такая проблема получила название - гонки. Если же у вас блокируется для паралельного доступа более одного объекта, то проблему которая возникает в этом случае называют: тупиками, взаимными блокировками и наиболее поэтично - смертельными объятиями (deadlock). Собственно, наличие слова Deadlock в сообщении об ошибке мне и позволило сделать предположение о такой проблеме.

    Более подробно про гонки и тупики можете посмотреть здесь.

    31 марта 2013 г. 6:47
    Отвечающий
  • Алексей, хороший у Вас блог!

    По описанию синхронизации потоков у Вас в Вашем блоге еще много работы -
    целый список полезных классов на все случаи жизни.
    В частности, помимо Semafore мне очень понравился,
    очень полезный для меня класс WaitHandle,
    реализующий дизъюнкцию потоков.
    31 марта 2013 г. 9:48
  • Алексей, хороший у Вас блог!

    Спасибо.
    В частности, помимо Semafore мне очень понравился,
    очень полезный для меня класс WaitHandle,
    реализующий дизъюнкцию потоков.

    Действительно в C# есть большое количество объектов для настройки синхронизации. Постоянно использовать все - смысла нет, нознать какие есть и что они могут - нужно.
    31 марта 2013 г. 16:13
    Отвечающий