C++ 为什么要将互斥量作为参数传递给线程调用的函数?

C++ 为什么要将互斥量作为参数传递给线程调用的函数?,c++,multithreading,boost,mutex,C++,Multithreading,Boost,Mutex,在一些地方,我看到人们创建线程池,创建线程,并用这些线程执行函数。调用该函数时,boost::mutex是通过引用传递的。为何要这样做?我相信可以在被调用函数本身中声明互斥,也可以声明为类成员或全局。谁能解释一下吗 e、 g 互斥对象是不可复制的对象,虽然它们可以是类的成员,但这将使父类的复制能力大大复杂化。因此,如果许多类实例需要共享相同的数据,一种首选方法是将互斥体创建为静态数据成员。否则,如果互斥体只需要在类本身的实例中锁定,您可以创建一个指向互斥体的指针作为非静态数据成员,然后类的每个副

在一些地方,我看到人们创建线程池,创建线程,并用这些线程执行函数。调用该函数时,boost::mutex是通过引用传递的。为何要这样做?我相信可以在被调用函数本身中声明互斥,也可以声明为类成员或全局。谁能解释一下吗

e、 g


互斥对象是不可复制的对象,虽然它们可以是类的成员,但这将使父类的复制能力大大复杂化。因此,如果许多类实例需要共享相同的数据,一种首选方法是将互斥体创建为静态数据成员。否则,如果互斥体只需要在类本身的实例中锁定,您可以创建一个指向互斥体的指针作为非静态数据成员,然后类的每个副本都有自己的动态分配互斥体(如果需要,还可以保持可复制)

在上面的代码示例中,基本上是通过引用将全局互斥传递到线程池中。这使共享相同内存位置的所有线程能够使用完全相同的互斥锁在该内存上创建独占锁,但无需管理互斥锁本身的不可复制方面的开销。此代码示例中的互斥体也可能是类
myClass
的静态数据成员,而不是通过引用传入的全局互斥体,假设每个线程都需要锁定一些可从每个线程全局访问的内存


本地互斥体的问题在于它只是互斥体的本地可访问版本。。。因此,当线程锁定互斥体以共享一些全局可访问的数据时,数据本身不受保护,因为每个其他线程都有自己的本地互斥体,可以锁定和解锁。它破坏了互斥的整体观点。

使用本地互斥是错误的:线程池可能会调用多个函数实例,它们应该使用相同的互斥。班上的人还好。将互斥体传递给函数使其更通用和可读。调用方可以决定传递哪个互斥体:类成员或其他任何对象

我相信可以在被调用函数本身中声明互斥,也可以声明为类成员或全局。谁能解释一下吗

在条目处创建新的互斥体不会保护任何内容

如果您考虑声明一个静态(或全局)互斥来保护非静态成员,那么您也可以将该程序编写为一个单线程程序(好的,有一些特殊情况)。静态锁将阻止除一个线程之外的所有线程(假设存在竞争);这相当于“一次最多可在该方法的主体中运行一个线程”。声明一个静态互斥来保护静态数据是可以的。正如David Rodriguez-dribeas在另一个答案的评论中简洁地说的那样:“互斥应该处于受保护的数据级别”

您可以为每个实例声明一个成员变量,其形式为:

class t_object {
public:
    ...
    bool getData(t_data& outData) {
        t_lock_scope lock(this->d_lock);
        ...
        outData.set(someValue);
        return true;
    }

private:
    t_lock d_lock;
};
这种方法很好,在某些情况下是理想的。在大多数情况下,当您构建一个实例打算从其客户端抽象锁定机制和错误的系统时,这是有意义的。一个缺点是,它可能需要更多的采集,并且通常需要更复杂的锁定机制(例如可重入)。通过更多的采集:客户机可能知道一个实例只在一个线程中使用:在这种情况下为什么要锁定?此外,一堆小型线程安全方法将引入大量开销。通过锁定,您希望尽快进出受保护区域(而不引入许多采集),因此关键部分通常比典型操作更大

如果公共接口需要此锁作为参数(如示例中所示),则表明可以通过私有化锁来简化设计(以线程安全的方式实现对象功能,而不是将锁作为外部持有的资源传递)

使用外部(或绑定或关联)锁,可以潜在地减少采集(或总锁定时间)。这种方法还允许您在事后向实例添加锁定。它还允许客户端配置锁的操作方式。客户端可以通过(在一组实例之间)共享锁来使用更少的锁。即使是一个简单的组合示例也可以说明这一点(支持两种模型):

类t_组合{
公众:
...
私人:

t_lock d_lock;//您应该在使用此选项的地方添加一个特定的示例。这很可能是由于示例中实现的语义造成的,并且在没有上下文的情况下根本无法回答(除非您想要泛型答案,因为这可能是有意义的答案)这毫无意义,在许多应用程序中,将互斥体作为非静态成员是有意义的。通常比将互斥体作为静态成员要多得多,而且没有理由不将指针或引用存储为成员。互斥体应处于受保护的数据级别(也就是说,如果它保护静态数据,那么它必须是静态的,如果它保护成员属性,那么它可能应该是一个成员,如果它由不同的实例或不同的类型共享,那么它必须是更一般的。对不起,我并不是说你不能这样做……我只是说,如果你将它设置为非静态数据成员,那么就可以创建一个正确的可复制类要困难得多(最终它不是真的可复制的,你必须存储一个指向互斥体的指针,然后在副本中释放和重新分配互斥体,这不是类中每个成员的“真实”副本)。我将修改我的答案以使其更清楚……这一切都取决于你对象的定义(语义上)在大多数情况下,互斥不构成对象状态的一部分,而是一个ut
    myClass::getData(boost::mutex& mutex)
    {
         boost::scoped_lock(mutex)    // Why can't we have class member variable mutex or                                     
                                      //local mutex here
        //Do somethign Here
}
class t_object {
public:
    ...
    bool getData(t_data& outData) {
        t_lock_scope lock(this->d_lock);
        ...
        outData.set(someValue);
        return true;
    }

private:
    t_lock d_lock;
};
class t_composition {
public:
    ...
private:
    t_lock d_lock; // << name and data can share this lock
    t_string d_name;
    t_data d_data;
};