Мьютекс - это то, что вы хватаете, и остановит любые другие потоки, пытаясь схватить его, пока вы не отпустите его от захватывающей нити.
В вашем вопросе у вас есть функция f, выделяющая экземпляр Mutex. Этого недостаточно, чтобы заблокировать его. Вам нужно специально называть mutex.lock() (в Qt, но также и вообще, если вы не используете pthread, в этом случае используйте pthread_mutex_lock и получайте удовольствие от низкоуровневого, зависящего от платформы материала. Qt очень хорошо его представляет).
вот пример с Qt
void MyClass::doStuff(int c)
{
mutex.lock();
a = c;
b = c * 2;
mutex.unlock();
}
После того, как вы получите блокировку, вызов г() будет сделано из потока, который получил замок, так что это будет один в этом вызове предполагающего, что вы не вызываете g() из других потоков из другой части кода. Блокировка не означает, что он остановит все остальные потоки. Это остановит поток, пытающийся получить тот же замок, пока не будет освобожден замок.
Если это единственный способ для ваших потоков достичь g(), то вы синхронизированы на этом доступе.
Для второй части вашего вопроса, если мьютекс является атрибутом экземпляра, то они будут двумя разными взаимными обозначениями. Вам нужно будет объявить и создать экземпляр экземпляра класса mutex и обратиться к нему за вашей блокировкой. В этом случае любая попытка вызова метода в классе, который блокирует мьютез класса, будет эффективно синхронизирована, а это означает, что ни один из двух потоков не будет выполнять этот метод вместе.
Например (я не имею Qt, поэтому я не могу скомпилировать этот код, и я прекратил кодирование с ней 2 года назад, так что он не мог работать)
class Foo {
public:
void method(void) {
mutex.lock();
cout << "method called";
// long computation
mutex.unlock();
}
private:
QMutex mutex;
};
Хорошо, в этом случае, предположим, что у вас есть два потока: 1 и 2 и два экземпляра класса Foo, a и b. Предположим, что поток 1 вызывает a.method(), а thread 2 вызывает b.method(). В этом случае два мьютекса представляют собой разные экземпляры, поэтому каждый поток будет выполнять вызов самостоятельно и запускаться параллельно.
Предположим, у вас есть два потока: 1 и 2 и один экземпляр класса Foo, который разделяется между двумя потоками. если поток 1 вызывает a.method(), а затем поток 2 вызывает a.method(), поток 2 остановится и дождитесь, пока не будет отключена блокировка мьютекса.
Наконец,
class Foo {
public:
void method(void) {
mutex.lock();
cout << "method called";
// long computation
mutex.unlock();
}
private:
static QMutex mutex;
};
QMutex Foo::mutex;
В этом случае мьютекс является статической переменной класса. У вас есть только один экземпляр мьютекса для каждого экземпляра объекта. Предположим, что у вас была такая же ситуация, как в первом случае: два потока и два экземпляра. В этом случае, когда второй поток пытается вызвать b.method(), ему придется дождаться, когда a.method() будет завершен первым потоком, поскольку блокировка теперь уникальна и распределена между всеми экземплярами вашего класса.
Для получения дополнительной информации, Qt имеет хороший учебник по многопоточности
https://doc.qt.io/qt-5/threads.html
+1 с использованием QT api –