Russian Qt Forum

Qt => Многопоточное программирование, процессы => Тема начата: serega-5508 от Июнь 28, 2011, 19:17



Название: QMutexLocker
Отправлено: serega-5508 от Июнь 28, 2011, 19:17
подскажите, пожалуйста, чем отличается QMutexLocker от QMutex в обработке исключений?


Название: Re: QMutexLocker
Отправлено: Igors от Июнь 28, 2011, 19:37
подскажите, пожалуйста, чем отличается QMutexLocker от QMutex в обработке исключений?
Тем же чем любой "scoped"
Код
C++ (Qt)
try {
QMutexLocker locker(&mutex);
...
}
catch (...) {
// деструктор  ~QMutexLocker выполнился,
// мутекс был освобожден, и, возможно, уже опять захвачен др. ниткой
// если это нежелательно - вынести определение locker за блок try
}
 


Название: Re: QMutexLocker
Отправлено: serega-5508 от Июнь 28, 2011, 21:11
и в чём тогда отличие, если что же самое может сделать и с QMutex???
Код:
try{
     QMutex mutex;
     mutex.lock();
     ....
     mutex.unlock();
}
catch(...){
              .......
              .......
}


Название: Re: QMutexLocker
Отправлено: BRE от Июнь 28, 2011, 21:42
и в чём тогда отличие, если что же самое может сделать и с QMutex???
А разве этот код делает тоже самое?
Если исключение произойдет в том месте которое ты обозначил ..... будет ли разлочен мьютек?


Название: Re: QMutexLocker
Отправлено: LisandreL от Июнь 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)


Название: Re: QMutexLocker
Отправлено: serega-5508 от Июнь 28, 2011, 22:17
LisandreL, спасибо большое за пояснение. Всё понял, очень доступно объяснили! СПАСИБО!


Название: Re: QMutexLocker
Отправлено: Igors от Июнь 29, 2011, 10:43
Код
C++ (Qt)
try{
    QMutex mutex;
}
Правильно
Код
C++ (Qt)
try{
    static QMutex mutex;
}
Я сделал такую же описку, на что в свое время указал мне BRE  :)


Название: Re: QMutexLocker
Отправлено: LisandreL от Июнь 29, 2011, 10:56
Я сделал такую же описку, на что в свое время указал мне BRE
Я из вашего кода и брал. Код вполне рабочий, хотя и бесполезный без дополнительного использования мьютекса в в середине.


Название: Re: QMutexLocker
Отправлено: Igors от Июнь 29, 2011, 11:24
Речь о том что локальная переменная mutex создается на стеке каждой из ниток и поэтому ничего не блокирует  :)


Название: Re: QMutexLocker
Отправлено: LisandreL от Июнь 29, 2011, 13:28
Речь о том что локальная переменная mutex создается на стеке каждой из ниток и поэтому ничего не блокирует  :)
Но ссылку на него можно предавать в функции для QtConcurrent::run как аргумент.


Название: Re: QMutexLocker
Отправлено: ритт от Июль 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 и, соответственно, для которого можно будет создавать статический экземпляр.


Название: Re: QMutexLocker
Отправлено: ритт от Июль 28, 2011, 10:30
Речь о том что локальная переменная mutex создается на стеке каждой из ниток и поэтому ничего не блокирует  :)
Но ссылку на него можно предавать в функции для QtConcurrent::run как аргумент.

только при использовании QFuture::waitForFinished() либо блокировок на том же мютексе.


Название: Re: QMutexLocker
Отправлено: Igors от Июль 29, 2011, 13:01
Igors, твой пример также некорректен (но по другим причинам). QMutex - не POD - создавая/используя его статический экземпляр в многопоточном приложении, ты рискуешь огрести в самый неожиданный момент. для данного примера правильным решением будет Q_GLOBAL_STATIC(QMutex, mutex)
Насколько я помню, ОС защищает такие инициализации (вызовы называются типв guard_acquire, guard_release). Но конечно неразумно/непрактично затруднять себя изучением этих деталей - гораздо проще определить mutex вне тела ф-ции.