互斥锁是你抓取的东西,它会阻止任何其他线程试图抓取它,直到你从抓取线程中释放它。
在您的问题中,您有一个分配 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(),它将在该调用中单独进行。锁定并不意味着它将停止所有其他线程。它将阻止线程试图获得相同的锁,直到锁被释放。
如果这是您的线程到达 g() 的唯一方法,那么您在该访问上是同步的。
对于您问题的第二部分,如果互斥锁是实例属性,那么它们将是两个不同的互斥锁。您必须声明和实例化一个类互斥体实例,并在锁定时引用它。在这种情况下,任何调用类中锁定类互斥锁的方法的尝试都将被有效同步,这意味着没有两个线程将一起执行该方法。
例如(我没有 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(),线程 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