Russian Qt Forum

Qt => Общие вопросы => Тема начата: 8Observer8 от Февраль 01, 2014, 08:11



Название: Возникновение тупиковых ситуаций (многопоточность)
Отправлено: 8Observer8 от Февраль 01, 2014, 08:11
Привет! Вот цитата из книги Макса Шлее:

Цитировать
Работая с многопоточностью, нужно помнить о возможном возникновении тупиковых си-
туаций, когда потоки могут заблокировать друг друга. Представьте себе такую ситуацию,
когда поток заблокировал ресурс "A", а после работы над ним собирается работать с ресур-
сом "B". Другой же поток заблокировал ресурс "B" и по окончании намеревается работать с
ресурсом "A". И вот один из потоков, закончив работу, обнаружил, что нужный ему ресурс
заблокирован другим потоком. Он переходит в режим ожидания, надеясь дождаться раз-
блокировки ресурса, но то же самое делает и другой поток. В итоге — оба ждут друг друга.
Если ни один из этих потоков не освободит занятый им ресурс, то оба "зависнут" и не смо-
гут продолжать свою работу дальше.

Вопрос: как мне кажется, когда поток закончит работу с ресурсом A, то он освободит этот ресурс. Или он будет его держать заблокированным до тех пор, пока не освободится ресурс B?


Название: Re: Возникновение тупиковых ситуаций (многопоточность)
Отправлено: Old от Февраль 01, 2014, 08:17
Как нипишите, так и будет. 


Название: Re: Возникновение тупиковых ситуаций (многопоточность)
Отправлено: 8Observer8 от Февраль 01, 2014, 08:19
Приведите, пожалуйста, простой пример? Я с потоками только начал знакомится. Для меня всё это неочивидно.


Название: Re: Возникновение тупиковых ситуаций (многопоточность)
Отправлено: 8Observer8 от Февраль 01, 2014, 08:38
Я так понимаю, что для правильного использования многопоточности в Qt, нужно сначала изучить примеры из папки "examples/threads", а потом "examples/qtconcurrent". А в дальнейшем использовать только модуль concurrent.

Если кто встречал ресурсы, где бы подробно и просто описывалось "Возникновение тупиковых ситуаций", то поделитесь, пожалуйста.


Название: Re: Возникновение тупиковых ситуаций (многопоточность)
Отправлено: Old от Февраль 01, 2014, 08:47
Приведите, пожалуйста, простой пример? Я с потоками только начал знакомится. Для меня всё это неочивидно.
Код
C++ (Qt)
mutex mut_a;
int a = 0;
 
mutex mut_b;
int b = 0;
 
void thread1()
{
   mut_a.lock();
   if( a == 100500 )
   {
       mut_b.lock();
       b = -100500;
       mut_b.unlock();
   }
   mut_a.unlock();
}
 
void thread2()
{
   mut_b.lock();
   if( b == 1 )
   {
       mut_a.lock();
       a = 0;
       mut_a.unlock();
   }
   mut_b.unlock();
}
 

Если потоки захватили по первому мютексу и условия оказались верны, то эти две нитки навсегда останутся ждать друг друга.


Название: Re: Возникновение тупиковых ситуаций (многопоточность)
Отправлено: Old от Февраль 01, 2014, 09:15
Я так понимаю, что для правильного использования многопоточности в Qt, нужно сначала изучить примеры из папки "examples/threads", а потом "examples/qtconcurrent". А в дальнейшем использовать только модуль concurrent.
Потоки это самый низкий уровень, QtConcurrent это более высокий уровень, позволяющий сконцентрироваться на решение задачи, не думая о потоках и синхронизациях.


Название: Re: Возникновение тупиковых ситуаций (многопоточность)
Отправлено: Igors от Февраль 01, 2014, 09:53
Я так понимаю, что для правильного использования многопоточности в Qt, нужно сначала изучить примеры из папки "examples/threads", а потом "examples/qtconcurrent". А в дальнейшем использовать только модуль concurrent.
"многопоточность в Qt" ничем не отличается от "не в Qt". Можно скользить по пути что Вы нарисовали: "прочитать букварь, посмотреть примеры и делать по образцу". В этом нет ничего плохого, устраивает - ну и хорошо. А можно и "копнуть". Если есть желание, вот Вам пара совсем простых задачек

1) Одна нитка принимает символ (напр с клавиатуры), другая его печатает
2) Сделать рекурсивный мутекс самому (на базе QMutex, но без использования QMutex::Recursive)

В процессе решения быстро и хорошо усвоите откуда возникает deadlock (о котором спрашиваете) и многое другое. 


Название: Re: Возникновение тупиковых ситуаций (многопоточность)
Отправлено: 8Observer8 от Февраль 01, 2014, 09:57
Спасибо,парни! Много подкинули пищи для размышления. Теперь это надо переварить. Результат переваривания выложу здесь.


Название: Re: Возникновение тупиковых ситуаций (многопоточность)
Отправлено: 8Observer8 от Февраль 02, 2014, 07:30
Я не очень-то понимал зачем вообще нужны многопоточные программы. Разве что было очевидно, если у компа несколько процессоров, то потоки будут выполнятся одновременно. А вот понять зачем это нужно на компьютере, где один процессор - немог. А тут открыл книжку "Чистый код" Мартин Р. и там есть главы "Многопоточность" (обзорно) и "Приложение A. Многопоточность 2" (подробно) и увидел показательные примеры:

Для примера возьмем однопоточныи агрегатор, который получает информацию
с многих сайтов и объединяет ее в ежедневную сводку. Так как система работает
в однопоточном режиме, она последовательно обращается к каждому сайту, всегда
завершая получение информации до перехода к следующему сайту. Ежедневный
сбор информации должен занимать менее 24 часов. Но по мере добавления новых
сайтов время непрерывно растет, пока в какой-то момент на сбор всех данных
не потребуется более 24 часов. Однопоточной реализации приходится подолгу
ожидать завершения операций ввода/вывода в сокетах. Для повышения 
производительности такого приложения можно было бы воспользоваться 
многопоточным алгоритмом, параллельно работающим с несколькими сайтами.


Или другой пример: допустим, система в любой момент времени работает только
с одним пользователем, обслуживание которого у нее занимает всего одну 
секунду. При малом количестве пользователей система оперативно реагирует на все
запросы, но с увеличением количества пользователей растет и время отклика. 
Никто не захочет стоять в очереди после 150 других пользователей! Время отклика
такой системы можно было бы улучшить за счет параллельного обслуживания
многих пользователей.

Или возьмем систему, которая анализирует большие объемы данных, но выдает
окончательный результат только после их полной обработки. Наборы данных
могут обрабатываться параллельно на разных компьютерах.


Название: Re: Возникновение тупиковых ситуаций (многопоточность)
Отправлено: Igors от Февраль 02, 2014, 07:44
Хоть неудобно спорить с таким авторитетом как "Мартин Р.", но все же выскажу свое мнение: все примеры - полное фуфло. Вяло, неконкретно, и вообще дезориентирует доверчивого читателя. Напр подталкивает его к мыслям типа "один коннект - одна нитка", и будет счастье. Впрочем наш читатель не очень-то хочет вникать, смотреть такие обзорняки приятно и ни к чему не обязывает  :)


Название: Re: Возникновение тупиковых ситуаций (многопоточность)
Отправлено: kuzulis от Февраль 02, 2014, 14:32
Эммм.. Например для ввода/вывода не обязательно ждать выполнения каких-то там сферических операций (на тех же сокетах). Потому что есть такая вешь - асинхронный ввод/вывод, где можно обойтись вообще одним потоком для всех сокетов, и прочих ресурсов ввода/вывода. А вот уже обработку/подготовку принятых/передаваемых данных можно/нужно переносить в отдельные потоки. Например какой нить парсинг или калькуляция может занимать время, поэтому пусть оно не мешает делать I/O, отрисовку GUI или прочие вещи. Хотя, ту же обработку данных можно "размазать" по времени и обойтись одним потоком. Например, делать не сразу все вычисления - а по одной операции.  :)