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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: QMutexLocker  (Прочитано 11927 раз)
serega-5508
Гость
« : Июнь 28, 2011, 19:17 »

подскажите, пожалуйста, чем отличается QMutexLocker от QMutex в обработке исключений?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #1 : Июнь 28, 2011, 19:37 »

подскажите, пожалуйста, чем отличается QMutexLocker от QMutex в обработке исключений?
Тем же чем любой "scoped"
Код
C++ (Qt)
try {
QMutexLocker locker(&mutex);
...
}
catch (...) {
// деструктор  ~QMutexLocker выполнился,
// мутекс был освобожден, и, возможно, уже опять захвачен др. ниткой
// если это нежелательно - вынести определение locker за блок try
}
 
Записан
serega-5508
Гость
« Ответ #2 : Июнь 28, 2011, 21:11 »

и в чём тогда отличие, если что же самое может сделать и с QMutex???
Код:
try{
     QMutex mutex;
     mutex.lock();
     ....
     mutex.unlock();
}
catch(...){
              .......
              .......
}
Записан
BRE
Гость
« Ответ #3 : Июнь 28, 2011, 21:42 »

и в чём тогда отличие, если что же самое может сделать и с QMutex???
А разве этот код делает тоже самое?
Если исключение произойдет в том месте которое ты обозначил ..... будет ли разлочен мьютек?
Записан
LisandreL
Птица говорун
*****
Offline Offline

Сообщений: 984


Надо улыбаться


Просмотр профиля
« Ответ #4 : Июнь 28, 2011, 21:45 »

QMutexLocker это вспомогательная, относительно QMutex'а вещь, позволяющая избежать неприятных ошибок.

Как раз ваш пример очень хорошо показывает проблему.

Код
C++ (Qt)
try{
    QMutex mutex;
    mutex.lock();
    ...
    x=1/x;
    ...
    mutex.unlock();
}
catch(...){
             .......
             .......
}
Если x=0, то mutex разрушается не будучи разлоченным, а это UB со всеми вытекающими.

Или другая схема:
Код
C++ (Qt)
QMutex mutex;
try{y=1/y;
    mutex.lock();
    ...
    x=1/x;
    ...
    mutex.unlock();
}
catch(...){
             // Если y==0, то mutex незалочен.
             // Если y!=0, а x==0, то mutex залочен.
             // Что делать?
             .......
             .......
}

Другой вариант использования - большая сложная функция, которая вся должна быть залочена.
Тогда перед каждым return'ом надо делать unlock, и если мы где-то его забываем => блокировка мьютекса навсегда.
Вместо этого можно написать в начале функции:
Код
C++ (Qt)
QMutexLocker locker( mutex );
Q_UNUSED(locker)
« Последнее редактирование: Июнь 28, 2011, 22:00 от LisandreL » Записан
serega-5508
Гость
« Ответ #5 : Июнь 28, 2011, 22:17 »

LisandreL, спасибо большое за пояснение. Всё понял, очень доступно объяснили! СПАСИБО!
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #6 : Июнь 29, 2011, 10:43 »

Код
C++ (Qt)
try{
    QMutex mutex;
}
Правильно
Код
C++ (Qt)
try{
    static QMutex mutex;
}
Я сделал такую же описку, на что в свое время указал мне BRE  Улыбающийся
Записан
LisandreL
Птица говорун
*****
Offline Offline

Сообщений: 984


Надо улыбаться


Просмотр профиля
« Ответ #7 : Июнь 29, 2011, 10:56 »

Я сделал такую же описку, на что в свое время указал мне BRE
Я из вашего кода и брал. Код вполне рабочий, хотя и бесполезный без дополнительного использования мьютекса в в середине.
« Последнее редактирование: Июнь 29, 2011, 10:59 от LisandreL » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #8 : Июнь 29, 2011, 11:24 »

Речь о том что локальная переменная mutex создается на стеке каждой из ниток и поэтому ничего не блокирует  Улыбающийся
Записан
LisandreL
Птица говорун
*****
Offline Offline

Сообщений: 984


Надо улыбаться


Просмотр профиля
« Ответ #9 : Июнь 29, 2011, 13:28 »

Речь о том что локальная переменная mutex создается на стеке каждой из ниток и поэтому ничего не блокирует  Улыбающийся
Но ссылку на него можно предавать в функции для QtConcurrent::run как аргумент.
Записан
ритт
Гость
« Ответ #10 : Июль 28, 2011, 10:28 »

Код
C++ (Qt)
try{
    QMutex mutex;
}
Правильно
Код
C++ (Qt)
try{
    static QMutex mutex;
}
Я сделал такую же описку, на что в свое время указал мне BRE  Улыбающийся

Igors, твой пример также некорректен (но по другим причинам). QMutex - не POD - создавая/используя его статический экземпляр в многопоточном приложении, ты рискуешь огрести в самый неожиданный момент. для данного примера правильным решением будет Q_GLOBAL_STATIC(QMutex, mutex)
возможно, в 5.0 появится QBasicMutex, который будет POD и, соответственно, для которого можно будет создавать статический экземпляр.
« Последнее редактирование: Июль 28, 2011, 10:31 от Константин » Записан
ритт
Гость
« Ответ #11 : Июль 28, 2011, 10:30 »

Речь о том что локальная переменная mutex создается на стеке каждой из ниток и поэтому ничего не блокирует  Улыбающийся
Но ссылку на него можно предавать в функции для QtConcurrent::run как аргумент.

только при использовании QFuture::waitForFinished() либо блокировок на том же мютексе.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #12 : Июль 29, 2011, 13:01 »

Igors, твой пример также некорректен (но по другим причинам). QMutex - не POD - создавая/используя его статический экземпляр в многопоточном приложении, ты рискуешь огрести в самый неожиданный момент. для данного примера правильным решением будет Q_GLOBAL_STATIC(QMutex, mutex)
Насколько я помню, ОС защищает такие инициализации (вызовы называются типв guard_acquire, guard_release). Но конечно неразумно/непрактично затруднять себя изучением этих деталей - гораздо проще определить mutex вне тела ф-ции.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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