Mutex to coś, co chwytasz, i zatrzyma wszelkie inne wątki próbujące go chwycić, dopóki nie zwolnisz go z wątku.
W swoim pytaniu masz funkcję f alokowania instancji Mutex. To nie wystarczy, aby go zablokować. Musisz wywołać mutex.lock() (w Qt, ale także ogólnie, chyba że używasz pthread, w tym przypadku użyj pthread_mutex_lock i baw się z niskopoziomowymi, zależnymi od platformy materiałami, Qt bardzo dobrze je streszcza).
tutaj jest przykład z Qt
void MyClass::doStuff(int c)
{
mutex.lock();
a = c;
b = c * 2;
mutex.unlock();
}
Gdy pojawi się zamek, wezwanie do g() zostanie wykonana z wątku, który dostał blokadę, więc to będzie sama w tej rozmowy zakładającej, że nie wywołujesz g() z innych wątków z innej części kodu. Blokowanie nie oznacza, że zatrzyma wszystkie pozostałe wątki. Spowoduje to przerwanie wątków próbujących uzyskać tę samą blokadę, aż do zwolnienia blokady.
Jeśli jest to jedyny sposób, w jaki twoje wątki docierają do g(), jesteś zsynchronizowany podczas tego dostępu.
W drugiej części pytania, jeśli muteks jest atrybutem instancji, będą to dwa różne muteksy. Będziesz musiał zadeklarować i utworzyć instancję klasy mutex i odwołać się do niej w celu zablokowania. W takim przypadku każda próba wywołania metody w klasie, która blokuje mutex klasy, będzie skutecznie zsynchronizowana, co oznacza, że żadne dwa wątki nie wykonają tej metody razem.
Na przykład (nie mam Qt, więc nie mogę skompilować ten kod, a ja przestałem kodowania z nim 2 lata temu, więc nie może pracować)
class Foo {
public:
void method(void) {
mutex.lock();
cout << "method called";
// long computation
mutex.unlock();
}
private:
QMutex mutex;
};
Ok, w takim przypadku, załóżmy, że masz dwa wątki, 1 i 2 oraz dwa wystąpienia klasy Foo, aib. Załóżmy, że wątek 1 wywołuje a.method(), a wątek 2 wywołuje b.method(). W tym przypadku dwa muteksy są różnymi instancjami, więc każdy wątek wykonuje wywołanie niezależnie i działa równolegle.
Załóżmy, że masz dwa wątki, 1 i 2 oraz jedno wystąpienie klasy Foo, która jest współużytkowana między dwoma wątkami. jeśli wątek 1 wywoła a.method(), a następnie wątek 2 wywoła a.method(), wątek 2 zatrzyma się i poczeka do zwolnienia blokady mutex.
Wreszcie
class Foo {
public:
void method(void) {
mutex.lock();
cout << "method called";
// long computation
mutex.unlock();
}
private:
static QMutex mutex;
};
QMutex Foo::mutex;
W tym przypadku, mutex jest zmienna statyczna klasa. Masz tylko jedną instancję muteksu dla każdej instancji obiektu. Załóżmy, że masz taką samą sytuację jak pierwszy przypadek powyżej: dwa wątki i dwa wystąpienia. W tym przypadku, gdy drugi wątek spróbuje wywołać b.method(), będzie musiał poczekać, aż a.method() zostanie zakończony przez pierwszy wątek, ponieważ blokada jest teraz unikatowa i współużytkowana przez wszystkie instancje klasy.
Aby uzyskać więcej informacji, Qt ma ładny tutorial wielowątkowość
https://doc.qt.io/qt-5/threads.html
+1 przy użyciu QT api –