Multithreading 互斥锁是否也适用于被调用的函数?

Multithreading 互斥锁是否也适用于被调用的函数?,multithreading,qt,mutex,Multithreading,Qt,Mutex,如果在函数中定义了互斥体,其锁是否应用于从该函数调用的函数?即 void f () { Mutex mutex; g(); } 锁是否仍适用于g()中的任何数据修改 另外,我说在类方法中定义的锁只适用于该类的特定实例,对吗?意思是: Class Foo; Foo foo1, foo2; (In thread 1) foo1.bar(); (In thread 2) foo2.bar(); 每个调用是否能够同时发生 如果有人能够解释/指出解释互斥锁背后机

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

void f () {  
    Mutex mutex;  
    g();  
}
锁是否仍适用于g()中的任何数据修改

另外,我说在类方法中定义的锁只适用于该类的特定实例,对吗?意思是:

Class Foo;  
Foo foo1, foo2;
(In thread 1) foo1.bar();  
(In thread 2) foo2.bar();  
每个调用是否能够同时发生


如果有人能够解释/指出解释互斥锁背后机制的链接,这将是一个很好的奖励。谢谢如果这些信息有帮助的话,我目前正在使用Qt线程库。

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

在您的问题中,您有一个分配互斥实例的函数。这还不足以锁定它。您必须专门调用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{
公众:
无效方法(void){
mutex.lock();

cout您的互斥体是在堆栈上本地建立的。因此,从一个线程调用f()将锁定其自己的互斥体实例。从另一个线程调用f()将锁定其自己的互斥体实例。因此,从g()访问数据时可能会出现争用情况!即使在同一类实例上调用它:

MyClass foo;
(In thread 1) foo->f();
(In thread 2) foo->f();

如何更好地处理锁取决于您想做什么。根据您所说的,我想更好的策略是直接修改g()实现:例如,它必须锁定声明为全局的互斥锁,或者在g()中声明为静态的互斥锁,以便在对g()的任何调用中共享。只要我知道您想全局锁定数据?

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

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

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.
  }

  // ...
};

在这种情况下,只要
ml
存在,
mutex
就会被锁定,线程在
g()
内的时间也会被锁定
在此期间,它将阻止创建其
ml
对象,直到第一个线程离开该函数,新线程可以锁定
互斥对象

对不起,我在伪代码方面做了一次非常糟糕的尝试。刚刚修复了它。您对第一部分的回答正是我想知道的,谢谢!如果我有数据的话我想锁定Foo::f()的特定实例,我应该将互斥体实例化为非静态类数据吗?我想应该这样做。然后,来自我示例中任何线程的“Foo”实例的任何调用都将阻止并发访问。(当然不是来自两个不同的实例)
MyClass foo;
(In thread 1) foo->f();
(In thread 2) foo->f();
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.
  }

  // ...
};