使用std :: mutex复制类

bha*_*esh 10 c++ c++11

我有一个以std :: mutex为成员的类.我正在尝试创建这样的类的数组

class C
{
 int x;
 std::mutex m;
};

int main()
{
  C c[10];
  //later trying to create a temp C
  C temp = c[0];
}
Run Code Online (Sandbox Code Playgroud)

显然,由于互斥对象不可复制,因此无法实现上述目标.解决它的方法是通过复制构造函数.

但是,我在创建复制构造函数时遇到问题.我试过了

C (const C &c)
{
   x = c.x;

   //1. m
   //2. m()
   //3. m = c.m
}
Run Code Online (Sandbox Code Playgroud)

我不确定3种选择中的正确语法是什么.请帮忙.

Pra*_*eep 8

简短的回答你不要复制互斥锁.

让我们从基础开始,互斥是一个互斥的简称,即你要确保当有多个线程时你不希望它们并行更改/修改值.您希望序列化访问或修改/读取,以便读取的值有效.

在上面的例子中,您将一个新值复制到变量.在这种情况下,您不需要在创建新对象时使用互斥锁.

  • 那你把互斥锁放在哪里呢? (2认同)
  • 这是如何被接受的答案? (2认同)

Max*_*kin 8

你可以使用一个数组shared_ptr<C>,然后你就不需要C它自己是可复制的......


mya*_*aut 8

你不应该写任何这些行.您的复制构造函数的实现等效于:

C (const C &c) : x(), m()
{
   x = c.x;
}
Run Code Online (Sandbox Code Playgroud)

所以互斥的新实例m默认初始化,这意味着默认的构造函数中的一个将被调用.它可以安全使用.

但是,有几个关于此代码的内容.即如果m保护x,您应该在访问值之前显式锁定它:

C (const C &c)
{
    std::lock_guard<std::mutex> (c.m);
    x = c.x;
}
Run Code Online (Sandbox Code Playgroud)

这需要声明m为可变(因为c在复制ctor中是const引用).

mutable std::mutex m;
Run Code Online (Sandbox Code Playgroud)

最后,您可以看到复制具有互斥体的对象是令人困惑的,如果C是公共类,则会使其用户感到困惑,因此在实现复制之前要三思而后行.

  • @ user4815162342:必须构造`c`,因为我们正在复制它,即:`C a; std :: thread([](const C&c){C tmp = c; cx = 20;},c)ax = 10;`。没有锁定互斥锁,这是竞争条件。 (2认同)