互斥锁上的锁也适用于被调用的函数吗?

int*_*nt3 8 qt multithreading mutex

如果在函数中定义了互斥锁,它的锁是否适用于从该函数调用的函数?即

void f () {  
    Mutex mutex;  
    g();  
}
Run Code Online (Sandbox Code Playgroud)

锁仍然适用于g()中的任何数据修改吗?

另外,我是否正确地说,类方法中定义的锁只适用于该类的特定实例?含义:

Class Foo;  
Foo foo1, foo2;
(In thread 1) foo1.bar();  
(In thread 2) foo2.bar();  
Run Code Online (Sandbox Code Playgroud)

每个电话会同时发生吗?

如果有人可以解释/指出解释互斥体背后机制的链接,那将是一个很好的奖励.谢谢!我目前正在使用Qt Thread库,如果该信息有帮助的话.

sth*_*sth 17

在您的示例中,您实际上并未锁定互斥锁,因此它不会阻止不同的线程同时访问该函数.您还在函数内部声明了互斥锁,以便每个函数调用使用不同的本地互斥对象.即使锁定此互斥锁,每个函数调用也会锁定不同的互斥锁对象,而不会阻止同时访问.

一个更好的策略是这样的设置:

class A {
  QMutex mutex;

  void f() {  
    QMutexLocker ml(mutex); // Acquire a lock on mutex
    g();

    // The lock on the mutex will be released when ml is destroyed.
    // This happens at the end of this function.
  }

  // ...
};
Run Code Online (Sandbox Code Playgroud)

在这种情况下mutex,只要ml存在就锁定,因此在线程花费的时间内也是如此g().如果另一个线程f()在此期间调用它将阻止创建其ml对象,直到第一个线程离开该函数并且新线程可以获得锁定mutex.


Ste*_*ini 8

一个互斥体是你抓住的东西,并且会阻止任何其他线程试图抓住它,直到你从抓取线程中释放它.

在您的问题中,您有一个函数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();
    } 
Run Code Online (Sandbox Code Playgroud)

一旦你获得锁定,对g()的调用将从获得锁定的线程完成,因此它将在该调用中独自一人,假设你没有从代码的另一部分调用来自其他线程的g().锁定并不意味着它将停止所有其他线程.它将阻止线程尝试获取相同的锁,直到锁被释放.

如果这是您的线程到达g()的唯一方法,那么您将在该访问上进行同步.

对于问题的第二部分,如果互斥锁是实例属性,那么它们将是两个不同的互斥锁.您将必须声明并实例化类互斥实例,并将其引用为您的锁定.在这种情况下,任何在类中锁定类互斥锁的方法调用的尝试都将被有效地同步,这意味着没有两个线程将一起执行该方法.

例如(我没有Qt,因此我无法编译此代码,并且我在2年前停止使用它编码,所以它无法工作)

class Foo {
public:
   void method(void) {
      mutex.lock();
      cout << "method called";
      // long computation
      mutex.unlock();
   }

private:
  QMutex mutex;
};
Run Code Online (Sandbox Code Playgroud)

好的,在这种情况下,假设你有两个线程,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;
Run Code Online (Sandbox Code Playgroud)

在这种情况下,互斥锁是一个类静态变量.每个对象实例只有一个互斥锁实例.假设您遇到与上述第一种情况相同的情况:两个线程和两个实例.在这种情况下,当第二个线程试图调用b.method()时,它必须等待第一个线程完成a.method(),因为锁现在是唯一的并且在类的所有实例之间共享.

有关更多信息,Qt有一个很好的多线程教程

https://doc.qt.io/qt-5/threads.html