Название: Помогите понять как работают мьютексы в Qt. Отправлено: lolbla2 от Март 29, 2012, 12:45 допустим есть разделяемый объект
Код
Есть общий мьютекс Код есть классы: Код
Так вот имеются вопросы: 1)когда th1 запустил он сделал lock() на мьютекс, а в этом время th2 уснёт что ли или что с ним вообще будет пока мьютекс заблочен? 2) Они оба пытаются заблокировать мьютекс, получается заблочит его тот кто быстрее успеет это сделать? Название: Re: Помогите понять как работают мьютексы в Qt. Отправлено: sudo от Март 29, 2012, 12:47 Кто первый встал, того и тапки. Один заблокировал, второй будет стоять и ждать, пока мьютекс разблокируется.
Есть ещё удобная штука - QMutexLocker, конструктор принимает указатель на мьютекс и сразу его блокирует, а в деструкторе разблокирует Название: Re: Помогите понять как работают мьютексы в Qt. Отправлено: mutineer от Март 29, 2012, 12:48 1) th2 будет сидеть в m.lock() и ждать пока мьютекс будет доступен
Название: Re: Помогите понять как работают мьютексы в Qt. Отправлено: lolbla2 от Март 29, 2012, 12:53 1) th2 будет сидеть в m.lock() и ждать пока мьютекс будет доступен то есть он уснёт пока, мьютекс не разблочат? Только не пойму что значит будет сидеть в m.lock(), то есть th2 выполнит m.lock() или нет? Значит вроде я всё правильно понимаю. а если сделать так Код
Тогда какое будет поведение у потоков? Название: Re: Помогите понять как работают мьютексы в Qt. Отправлено: mutineer от Март 29, 2012, 12:54 Отработают параллельно, возможно испортив buf
Название: Re: Помогите понять как работают мьютексы в Qt. Отправлено: lolbla2 от Март 29, 2012, 13:00 Отработают параллельно, возможно испортив buf Можно поподробнее 1 случай: 1. th1: m.lock() - выполнил th2: дошёл до строчки m.lock() не выполнил её и уснул, т.к. оказалось что мьютекс уже заблочен 2.th1: buf.append("Th1"); добавил в буффер, пошёл на m.unlock() - разблочил мьютекс, запустил цикл обработки событий. th2: спит, как только th1 сделал m.unlock() так сразу th2 заблочил мьютекс m.lock() добавил в буффер сообщение и далее m.unlock() - разблочил мьютекс и запустил свой цикл обработки событий. Всё верно? если не так поправьте меня) Название: Re: Помогите понять как работают мьютексы в Qt. Отправлено: mutineer от Март 29, 2012, 13:01 В принципе да, все правильно
Название: Re: Помогите понять как работают мьютексы в Qt. Отправлено: Igors от Март 29, 2012, 13:56 Можно поподробнее 1 случай: Верно, + важно понимать: во времени операции из разных ниток th1/th2 выполняются в ЛЮБОМ порядке. Общий мутекс гарантирует только что одна (и только одна) нитка будет выполнять защищенный участок. Др предположения неверны: напр запустили первой th1. потом th2, но оказывается th2 первой захватила мутекс. Или напр th1 первой добавила в буфер, но th2 первой запустила свой exec и получила сигнал1. th1: m.lock() - выполнил th2: дошёл до строчки m.lock() не выполнил её и уснул, т.к. оказалось что мьютекс уже заблочен 2.th1: buf.append("Th1"); добавил в буффер, пошёл на m.unlock() - разблочил мьютекс, запустил цикл обработки событий. th2: спит, как только th1 сделал m.unlock() так сразу th2 заблочил мьютекс m.lock() добавил в буффер сообщение и далее m.unlock() - разблочил мьютекс и запустил свой цикл обработки событий. Всё верно? если не так поправьте меня) Ну и вообще-то мутексы везде так работают, не только в Qt Название: Re: Помогите понять как работают мьютексы в Qt. Отправлено: lolbla2 от Март 29, 2012, 14:08 Можно поподробнее 1 случай: Верно, + важно понимать: во времени операции из разных ниток th1/th2 выполняются в ЛЮБОМ порядке. Общий мутекс гарантирует только что одна (и только одна) нитка будет выполнять защищенный участок. Др предположения неверны: напр запустили первой th1. потом th2, но оказывается th2 первой захватила мутекс. Или напр th1 первой добавила в буфер, но th2 первой запустила свой exec и получила сигнал1. th1: m.lock() - выполнил th2: дошёл до строчки m.lock() не выполнил её и уснул, т.к. оказалось что мьютекс уже заблочен 2.th1: buf.append("Th1"); добавил в буффер, пошёл на m.unlock() - разблочил мьютекс, запустил цикл обработки событий. th2: спит, как только th1 сделал m.unlock() так сразу th2 заблочил мьютекс m.lock() добавил в буффер сообщение и далее m.unlock() - разблочил мьютекс и запустил свой цикл обработки событий. Всё верно? если не так поправьте меня) Ну и вообще-то мутексы везде так работают, не только в Qt Хочешь сказать, что если нитка th1 первой добавила сообщение, но нитка th2 может быстрее запустить свой цикл событий, так как ей больше процессорного времени досталось? Название: Re: Помогите понять как работают мьютексы в Qt. Отправлено: Bepec от Март 29, 2012, 14:22 Да. Они не зависят друг от друга.
Т.е. не рассчитывай на последовательное изменение ;) скорее на хаотичное :D Название: Re: Помогите понять как работают мьютексы в Qt. Отправлено: Igors от Март 29, 2012, 14:34 Хочешь сказать, что если .. Ну если Вы такой резвый, то вот Вам задачка- сделать так чтобы нитки th1 и th2 (стартовавшие в любом порядке) добавили в буфер данные в строго определенном порядке - сначала th1, потом th2 А то бомбить вопросами легко :) Название: Re: Помогите понять как работают мьютексы в Qt. Отправлено: Bepec от Март 29, 2012, 14:40 Хм и меня заинтересовал вопрос :)
Взаимо********, пара***** сигн****? Название: Re: Помогите понять как работают мьютексы в Qt. Отправлено: lolbla2 от Март 29, 2012, 16:05 Хочешь сказать, что если .. Ну если Вы такой резвый, то вот Вам задачка- сделать так чтобы нитки th1 и th2 (стартовавшие в любом порядке) добавили в буфер данные в строго определенном порядке - сначала th1, потом th2 А то бомбить вопросами легко :) Через QWaitCondition можно сделать думаю. Название: Re: Помогите понять как работают мьютексы в Qt. Отправлено: Igors от Март 29, 2012, 16:22 Через QWaitCondition можно сделать думаю. Ну так делайте :)Примечание: использование QWaitCondition и QSemaphore часто равноценно. Мне лично логика семафора нравится гораздо больше, вероятно просто потому что это был первый примитив который я освоил (у другого может быть наоборот). Название: Re: Помогите понять как работают мьютексы в Qt. Отправлено: Bepec от Март 29, 2012, 16:56 Агась. :D я WaitCondition освоил первым :D
Название: Re: Помогите понять как работают мьютексы в Qt. Отправлено: BRE от Март 29, 2012, 17:04 Примечание: использование QWaitCondition и QSemaphore часто равноценно. К сожалению нет.При использовании условных переменных ядро разбудит одну из нитей (ожидающих эту переменную) вне очереди, а при семафорах нитка проснется и продолжит выполнение, только дождавшись своей очереди. Название: Re: Помогите понять как работают мьютексы в Qt. Отправлено: Igors от Март 29, 2012, 17:13 К сожалению нет. Несколько ниток ждут на одном семафоре. Кто-то просигналил, семафор открылся, и одна из ниток его захватила. Чем здесь WaitCondition выгоднее?При использовании условных переменных ядро разбудит одну из нитей (ожидающих эту переменную) вне очереди, а при семафорах нитка проснется и продолжит выполнение, только дождавшись своей очереди. Название: Re: Помогите понять как работают мьютексы в Qt. Отправлено: BRE от Март 29, 2012, 17:26 У процесса 10 ниток. Пусть они выполняются в порядке их номеров.
Нитки 1, 2, 3 ждут на условной переменной, нитка 4 делает wakeOne, ядро может разбудить одну из ниток 1-3. При семафоре: сначала отработают нитки 5-10, и только потом нитка 1 получит управление и захватит семафор. Название: Re: Помогите понять как работают мьютексы в Qt. Отправлено: Igors от Март 29, 2012, 18:27 У процесса 10 ниток. Пусть они выполняются в порядке их номеров. Т.е. нитка(и) ждущая на семафоре проснется только тогда когда ОС выделит ей квант времени? А на условной переменной нет? Никогда не слышал о таком, дайте линк. СпасибоНитки 1, 2, 3 ждут на условной переменной, нитка 4 делает wakeOne, ядро может разбудить одну из ниток 1-3. При семафоре: сначала отработают нитки 5-10, и только потом нитка 1 получит управление и захватит семафор. Также уточните о чем Вы говорите: о системных вызовах sem_wait и pthread_cond_wait или как? Потому что в Qt оба реализованы на pthread_cond_wait, и с этой точки зрения разницы нет. Спускаясь на землю - семафор примитивнее, но часто именно эта простота и нужна. Число побудок равно числу просыпающихся - и все дела. Идеально для создатель-потребитель. WaitCondition хитрее, побудка может и не иметь эффекта. Но зато надо думать "хз а не проскочит ли". Зачем усложнять когда семафор делает все что нужно? Название: Re: Помогите понять как работают мьютексы в Qt. Отправлено: BRE от Март 29, 2012, 19:20 Т.е. нитка(и) ждущая на семафоре проснется только тогда когда ОС выделит ей квант времени? А на условной переменной нет? Никогда не слышал о таком, дайте линк. Спасибо А ты поищи сам.Я не все читаю в интернете и не всегда могу точно вспомнить источник. Это могла быть печатная статья, книга или исходники ядра linux. Также уточните о чем Вы говорите: о системных вызовах sem_wait и pthread_cond_wait или как? Потому что в Qt оба реализованы на pthread_cond_wait, и с этой точки зрения разницы нет. Я говорил про pthread_cond_xxx и sem_xx. Если в Qt и QWaitCondition и QSemaphore выполнен на условных переменных, то разницы конечно нет.Но зато надо думать "хз а не проскочит ли". Кто и куда не проскочит?Название: Re: Помогите понять как работают мьютексы в Qt. Отправлено: Igors от Март 29, 2012, 20:29 Кто и куда не проскочит? Вот пример из букваря (только выкинул sleep)Код Пусть потребитель увлечен тем do_something, на кеуpressed (он же condition) никто не ждет. Значит эффект wakeAll нулевой. Шустрый пользователь успевает ввести еще getchar - вот и "проскочило" Кроме того, я лично недопонимаю один момент. С точки зрения "ожидающего побудки" все ясно Код
А вот что с будящим.... Код
Объясните. Спасибо Название: Re: Помогите понять как работают мьютексы в Qt. Отправлено: Bepec от Март 29, 2012, 20:46 Помоему ваш пример насчёт нажатия кнопки ээээ... Как бы сказать - высосан из пальца.
Насчёт мутексов / разблокировки - я твой пример не понимаю. Если разные потоки, то это будут разные мутексы. И ваше wakeAll не будет иметь эффекта. Если один поток, то там (в простейшей ситуации) будет 1 мьютекс, который собственно лочится/анлочится. Если честно не понимаю вообще вашего примера. WaitCondition ждёт пробуждения. Функция do_something() не должна являться рекурсивной, иначе теряется смысл WaitCondition. WakeCondition (по моему мнению) идеальный вариант сигнала обработки данных. Засыпаем. Данные добавляются. Побудка. Просыпаемся. Обрабатываем всю пришедшую информацию. Засыпаем. А насчёт использовать его аналогично обычному сигналу (тот же keyPressed) помоему извращение. Как Семафор в качестве переменной int к примеру ;) Название: Re: Помогите понять как работают мьютексы в Qt. Отправлено: BRE от Март 29, 2012, 22:22 Пусть потребитель увлечен тем do_something, на кеуpressed (он же condition) никто не ждет. Значит эффект wakeAll нулевой. Шустрый пользователь успевает ввести еще getchar - вот и "проскочило" Так очереди уже изобрели.так чей же мутекс??? Мой или того кто проснулся? Еще никто не проснулся, нитка с wait отметилась как готовая к исполнению, но она не проснется пока ты не освободишь мьютекс.Название: Re: Помогите понять как работают мьютексы в Qt. Отправлено: Igors от Март 30, 2012, 00:47 Помоему ваш пример насчёт нажатия кнопки ээээ... Как бы сказать - высосан из пальца. Как уже говорилось, это пример их букваря (Assistant)Насчёт мутексов / разблокировки - я твой пример не понимаю. .. Если честно не понимаю вообще вашего примера. WakeCondition (по моему мнению) идеальный вариант сигнала обработки данных. Это как раз сценарий семафора - мы всегда можем спокойно положиться на него. В случае waitCondition надо считаться с тем что побудка может прийти когда мы заняты обработкой. Это может быть и выгоднееЗасыпаем. Данные добавляются. Побудка. Просыпаемся. Обрабатываем всю пришедшую информацию. Засыпаем. Код
Еще никто не проснулся, нитка с wait отметилась как готовая к исполнению, но она не проснется пока ты не освободишь мьютекс. Ну да, по-другому не видно как. Но смущает что в манах это "не звучит" :)Название: Re: Помогите понять как работают мьютексы в Qt. Отправлено: Bepec от Март 30, 2012, 07:02 Я возможно невнимателен, возможно просто инитуитивно использую его именно в этом ключе. Как ожидающий поступления данных, с возможностью "проскакивания".
Причём в моих случаях, WaitCondition выгоднее семафора и "проще". PS хотя кто знает, мб я его использую не так, как задумывали разработчики,но "это работает". Название: Re: Помогите понять как работают мьютексы в Qt. Отправлено: Igors от Март 30, 2012, 13:30 Причём в моих случаях, WaitCondition выгоднее семафора и "проще". Как и наоборот :) Вот задачка "проще некуда" - одна нитка читает консольный символ, другая печатает просто "pressed". Реализация любителя семафоровКод А как это сделать на QWaitCondition ? Название: Re: Помогите понять как работают мьютексы в Qt. Отправлено: Bepec от Март 30, 2012, 14:15 В приведённом вами примере, нет необходимости в ожидании. Семафор там используется просто как посыл сигнала.
Скажем проще - в ситуации: Неизвестно когда/что/кто/сколько добавит и надо обработать - waitCondition полезно. (обработка всех добавленных данных и опять спячка) А когда: Ожидаем действия пользователя и вызываем адекватную реакцию - тут уже семафоры/сигналы. WaitCondition не позиционируется как сигнал/система реального времени (мб перемудрил с определением). Он не даст адекватной быстрой реакции в ваших примерах. А вот в случае аля "слушаем 500 устройств, возможно кто-то что-то пришлёт, а присланное и разобрать надо неизвестной длины" - тогда уже wait рулит ;) PS возможно их использование и как аналогов, но они разного принципа ;) Название: Re: Помогите понять как работают мьютексы в Qt. Отправлено: Igors от Март 30, 2012, 14:41 Реализация с семафором проста и понятна - по 2 строчки на нитку. А что с WaitCondition? С высказанными общими соображениями я вполне согласен, ну а делать-то что? Приводим псевдокод или признаем что такую мелочь оказывается сложно сделать на condition :)
Название: Re: Помогите понять как работают мьютексы в Qt. Отправлено: BRE от Март 30, 2012, 15:27 Реализация с семафором проста и понятна - по 2 строчки на нитку. А что с WaitCondition? С высказанными общими соображениями я вполне согласен, ну а делать-то что? Приводим псевдокод или признаем что такую мелочь оказывается сложно сделать на condition :) Ну если QSemaphore сделан на QWaitCondition, то можно развернуть методы семафора. :)Посмотрел что сейчас делается на этом фронте... Для систем с многоядерными процессорами есть один момент. Условная переменная имеет возможность подготовить к пробуждению одну нитку из нескольких ждущих, а с семафорами похуже. Ядро готовит к пробуждению все нитки ждущие на семафоре, что бы они в конкурентной борьбе могли захватить ресурс. Т.е. ждут пять ниток, появился один ресурс, все проснулись, самая быстрая его захватили, все остальные проверили и заснули дальше. Название: Re: Помогите понять как работают мьютексы в Qt. Отправлено: Bepec от Март 30, 2012, 17:40 Igors, вы мне предлагаете выложить вам вариант костыля использования QWaitCondition в роли семафора. :)
А выложите-ка вы мне сначала пример реализации "проскакивающего" пробуждения (вы ведь ранее его сами приводили и недоумевали), используя Семафор заместо WaitCondition. PS вот сейчас вы конкретно неправильно ставите вопрос. Это разные классы с почти одинаковыми возможностями. Но только почти. Название: Re: Помогите понять как работают мьютексы в Qt. Отправлено: Igors от Март 30, 2012, 18:03 Igors, вы мне предлагаете выложить вам вариант костыля использования QWaitCondition в роли семафора. :) А чего это Вы мне так сразу поверили что здесь семафор якобы лучше? :) QWaitCondition ничем не хуже, ну надо написать по 4 строчки на нитку вместо 2, чего торгуетесь? :) Если у Вас трудности - я напишу, не вопрос. А не надо - ну так и проехали.Название: Re: Помогите понять как работают мьютексы в Qt. Отправлено: Bepec от Март 30, 2012, 18:04 Таки я ответил на ваш вопрос ещё раньше - почитайте мои предыдущие сообщения. WaitCondition ждёт / отрабатывает / засыпает.
Название: Re: Помогите понять как работают мьютексы в Qt. Отправлено: Igors от Март 30, 2012, 19:04 Посмотрел что сейчас делается на этом фронте... Интересно, где читаете?Для систем с многоядерными процессорами есть один момент. Условная переменная имеет возможность подготовить к пробуждению одну нитку из нескольких ждущих, а с семафорами похуже. Ядро готовит к пробуждению все нитки ждущие на семафоре, что бы они в конкурентной борьбе могли захватить ресурс. Т.е. ждут пять ниток, появился один ресурс, все проснулись, самая быстрая его захватили, все остальные проверили и заснули дальше. Неясно конечно в чем заключается та "подготовка к пробуждению". И вот с "одной" - ведь в ОC wake будит "хотя бы одну", но может и больше, какую тогда готовит? Понятно не все вопросы имеют (простые) ответы. Название: Re: Помогите понять как работают мьютексы в Qt. Отправлено: BRE от Март 30, 2012, 20:06 Неясно конечно в чем заключается та "подготовка к пробуждению". Изменение состояния нитки - флаг поменять. Ядро для каждого объекта синхронизации хранит очередь ниток, которые ожидают освобождения этого объекта. Все они имеют состояние останова. Что бы пробудить нужно это состояние поменять.И вот с "одной" - ведь в ОC wake будит "хотя бы одну", но может и больше, какую тогда готовит? Понятно не все вопросы имеют (простые) ответы. С условными переменными, я как разработчик, могу сказать ядру разбуди одну нить (wakeOne) не важно какую или разбудить все ожидающие нити (wakeAll).Если я добавил одно задание в очередь заданий, то мне не нужно будить все ожидающие нити, мне будет достаточно одной. А если мне нужно, что бы все нитки завершились, то я устанавливаю флаг и прошу проснутся всех. У семафоров такой возможности нет. |