Russian Qt Forum
Ноябрь 23, 2024, 07:10 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2 3   Вниз
  Печать  
Автор Тема: Помогите понять как работают мьютексы в Qt.  (Прочитано 24025 раз)
lolbla2
Гость
« : Март 29, 2012, 12:45 »

допустим есть разделяемый объект

Код
C++ (Qt)
QBuffer buf;

Есть общий мьютекс
Код
QMutex m;
есть классы:

Код
C++ (Qt)
class Th1: public QThread
{
public:    
void run();
}
void Th1::run()
{
    m.lock();
    buf.append("Th1");
    m.unlock();
    exec();
}
 
class Th2: public QThread
{
public:    
void run();
}
void Th2::run()
{
    m.lock();
    buf.append("Th2");
    m.unlock();
    exec();
}
 
Th1 th1;
Th2 th2;
th1.start();
th2.start();
 

Так вот имеются вопросы:

1)когда th1 запустил он сделал lock() на мьютекс, а в этом время th2 уснёт что ли или что с ним вообще будет пока мьютекс заблочен?
2) Они оба пытаются заблокировать мьютекс, получается заблочит его тот кто быстрее успеет это сделать?


Записан
sudo
Гость
« Ответ #1 : Март 29, 2012, 12:47 »

Кто первый встал, того и тапки. Один заблокировал, второй будет стоять и ждать, пока мьютекс разблокируется.

Есть ещё удобная штука - QMutexLocker, конструктор принимает указатель на мьютекс и сразу его блокирует, а в деструкторе разблокирует
Записан
mutineer
Гость
« Ответ #2 : Март 29, 2012, 12:48 »

1) th2 будет сидеть в m.lock() и ждать пока мьютекс будет доступен
Записан
lolbla2
Гость
« Ответ #3 : Март 29, 2012, 12:53 »

1) th2 будет сидеть в m.lock() и ждать пока мьютекс будет доступен

то есть он уснёт пока, мьютекс не разблочат? Только не пойму что значит будет сидеть в m.lock(), то есть th2 выполнит m.lock() или нет?
Значит вроде я всё правильно понимаю.

а если сделать так

Код
C++ (Qt)
QMutex m1;
QMutex m2;
class Th1: public QThread
{
public:    
void run();
}
void Th1::run()
{
    m1.lock();
    buf.append("Th1");
    m1.unlock();
    exec();
}
 
class Th2: public QThread
{
public:    
void run();
}
void Th2::run()
{
    m2.lock();
    buf.append("Th2");
    m2.unlock();
    exec();
}
 
Th1 th1;
Th2 th2;
th1.start();
th2.start();

Тогда какое будет поведение у потоков?
« Последнее редактирование: Март 29, 2012, 12:55 от lolbla2 » Записан
mutineer
Гость
« Ответ #4 : Март 29, 2012, 12:54 »

Отработают параллельно, возможно испортив buf
Записан
lolbla2
Гость
« Ответ #5 : Март 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() - разблочил мьютекс и запустил свой цикл обработки событий.

Всё верно? если не так поправьте меня)
Записан
mutineer
Гость
« Ответ #6 : Март 29, 2012, 13:01 »

В принципе да, все правильно
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #7 : Март 29, 2012, 13:56 »

Можно поподробнее 1 случай:
1. th1: m.lock() - выполнил th2: дошёл до строчки m.lock() не выполнил её и уснул, т.к. оказалось что мьютекс уже заблочен
2.th1: buf.append("Th1"); добавил в буффер, пошёл на m.unlock() - разблочил мьютекс, запустил цикл обработки событий. th2: спит, как только th1 сделал m.unlock() так сразу th2 заблочил мьютекс m.lock() добавил в буффер сообщение и далее m.unlock() - разблочил мьютекс и запустил свой цикл обработки событий.

Всё верно? если не так поправьте меня)
Верно, + важно понимать: во времени операции из разных ниток th1/th2 выполняются в ЛЮБОМ порядке. Общий мутекс гарантирует только что одна (и только одна) нитка будет выполнять защищенный участок. Др предположения неверны: напр запустили первой th1. потом th2, но оказывается th2 первой захватила мутекс. Или напр th1 первой добавила в буфер, но th2 первой запустила свой exec и получила сигнал

Ну и вообще-то мутексы везде так работают, не только в Qt
« Последнее редактирование: Март 29, 2012, 13:58 от Igors » Записан
lolbla2
Гость
« Ответ #8 : Март 29, 2012, 14:08 »

Можно поподробнее 1 случай:
1. th1: m.lock() - выполнил th2: дошёл до строчки m.lock() не выполнил её и уснул, т.к. оказалось что мьютекс уже заблочен
2.th1: buf.append("Th1"); добавил в буффер, пошёл на m.unlock() - разблочил мьютекс, запустил цикл обработки событий. th2: спит, как только th1 сделал m.unlock() так сразу th2 заблочил мьютекс m.lock() добавил в буффер сообщение и далее m.unlock() - разблочил мьютекс и запустил свой цикл обработки событий.

Всё верно? если не так поправьте меня)
Верно, + важно понимать: во времени операции из разных ниток th1/th2 выполняются в ЛЮБОМ порядке. Общий мутекс гарантирует только что одна (и только одна) нитка будет выполнять защищенный участок. Др предположения неверны: напр запустили первой th1. потом th2, но оказывается th2 первой захватила мутекс. Или напр th1 первой добавила в буфер, но th2 первой запустила свой exec и получила сигнал

Ну и вообще-то мутексы везде так работают, не только в Qt

Хочешь сказать, что если нитка th1 первой добавила сообщение, но нитка th2 может быстрее запустить свой цикл событий, так как ей больше процессорного времени досталось?
Записан
Bepec
Гость
« Ответ #9 : Март 29, 2012, 14:22 »

Да. Они не зависят друг от друга.

Т.е.  не рассчитывай на последовательное изменение Подмигивающий скорее на хаотичное Веселый
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #10 : Март 29, 2012, 14:34 »

Хочешь сказать, что если ..
Ну если Вы такой резвый, то вот Вам задачка

- сделать так чтобы нитки th1 и th2 (стартовавшие в любом порядке) добавили в буфер данные в строго определенном порядке - сначала th1, потом th2

А то бомбить вопросами легко  Улыбающийся
« Последнее редактирование: Март 29, 2012, 14:36 от Igors » Записан
Bepec
Гость
« Ответ #11 : Март 29, 2012, 14:40 »

Хм и меня заинтересовал вопрос Улыбающийся

Взаимо********, пара***** сигн****?
Записан
lolbla2
Гость
« Ответ #12 : Март 29, 2012, 16:05 »

Хочешь сказать, что если ..
Ну если Вы такой резвый, то вот Вам задачка

- сделать так чтобы нитки th1 и th2 (стартовавшие в любом порядке) добавили в буфер данные в строго определенном порядке - сначала th1, потом th2

А то бомбить вопросами легко  Улыбающийся

Через QWaitCondition можно сделать думаю.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #13 : Март 29, 2012, 16:22 »

Через QWaitCondition можно сделать думаю.
Ну так делайте  Улыбающийся

Примечание: использование QWaitCondition и QSemaphore часто равноценно. Мне лично логика семафора нравится гораздо больше, вероятно просто потому что это был первый примитив который я освоил (у другого может быть наоборот).
Записан
Bepec
Гость
« Ответ #14 : Март 29, 2012, 16:56 »

Агась. Веселый я WaitCondition освоил первым Веселый
Записан
Страниц: [1] 2 3   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.37 секунд. Запросов: 24.