繁体   English   中英

Boost,指向互斥量的指针,会起作用吗? boost :: mutex和std :: vector,不可复制的问题

[英]Boost, pointer to a mutex, will that work? boost::mutex and std::vector, noncopyable issue

以下代码会给我一个错误,因为boost :: mutex是不可复制的,而xyz.push_back()是复制构造函数。

class XYZ
{
    public:
        double x;
        boost::mutex x_mutex;
}

vector<XYZ> xyz;
xyz.push_back(XYZ());

所以我尝试了这样的事情,

class XYZ
{
    public:
        double x;
        boost::mutex * x_mutex;
}

vector<XYZ> xyz;
xyz.push_back(XYZ());

它没有错误,但是问题是“互斥锁实际上会按预期工作吗?” 这是将互斥体封装在类中,然后创建该类的向量的好方法吗?

谢谢。

这里有两个问题:

  1. 是否可以正确创建互斥锁?

  2. 互斥锁是否可以正确使用?

就问题而言,对1.的答案是否定的。 互斥锁指针未指向互斥锁。

因此,您需要添加适当的构造函数。 而且由于您需要构造函数,因此如果您希望类正常运行,则可能需要实现析构函数,复制构造函数和赋值运算符。

XYZ::XYZ() : x(0), x_mutex(new boost::mutex) {}
XYZ::~XYZ() { delete x_mutex; }
XYZ::XYZ( const XYZ & xyz ) : x(xyz.x), x_mutex( new boost::mutex ) {}
XYZ& XYZ::operator=( const XYZ & xyz ) { x=xyz.x; }

要么

explicit XYZ::XYZ( boost::mutex * m ) : x(0), x_mutex(m) {}
// Strictly speaking we dont need these as the default version does the right thing.
XYZ::~XYZ() {}
XYZ::XYZ( const XYZ & xyz ) : x(xyz.x), x_mutex( xyz.x_mutex ) {}
XYZ& XYZ::operator=( const XYZ & xyz ) { x=xyz.x; x_mutex = xyz.x_mutex; }

会是我所期望的。

在第一种情况下,对象的每个实例和副本都有其自己的互斥体。 在第二个对象中,每个对象与其副本共享一个互斥体,但是该互斥体必须在实例之前创建。

还有第三个变体,其中互斥量可以由构造函数创建并与所有实例共享,但是要做到这一点,您可以将shared_ptr保留给互斥量,而不是原始指针。

class XYZ
{
  public:
    double x;
    boost::shared_ptr<boost::mutex> x_mutex;
    XYZ() : x(0), x_mutex( new boost::mutex ) {}
    // Default versions of the other three do the right thing.
};

如果沿着这些路径中的任何一条走下去,最终将导致互斥体被正确创建和初始化的情况。

现在,对于棘手的部分“是否可以正确使用互斥锁?”。 为了回答这个问题,我们需要知道线程之间如何共享对象,互斥体应该保护什么共享数据。

如果对象向量是在创建任何工作线程之前在主线程中创建的,并且每个对象实例都已被工作线程修改(以便互斥锁确实在保护x数据),则第一个版本(如果可能的话)是正确的。 在这种情况下,您的代码看起来更像这样。

//Main thread
std::vector<XYZ> v;
for(unsigned int i=0; i<10; ++i)
  v.push_back(XYZ());

//Several worker threads like this
j = rand()%10;
v[j].x_mutex->lock();
v[j].x+=1;
v[j].x_mutex->unlock();

如果x确实是指针类型,并且它所指向的对象在线程之间共享,那么您的代码可能看起来像这样,并且要使用的正确代码版本是2或3。

//Main thread
std::vector<XYZ> v;
X * xa;
boost::mutex xa_mutex;
X * xb;
boost::mutex xb_mutex;

for(unsigned int i=0; i<5; ++i)
  v.push_back(XYZ(xa,xa_mutex));

for(unsigned int i=0; i<5; ++i)
  v.push_back(XYZ(xb,xb_mutex));

//Several worker threads like this
j = rand()%10;
v[j].x_mutex->lock(); 
v[j].x->do_something();
v[j].x_mutex->unlock();

关键是每个共享资源只有一个互斥量。

请注意,从技术上讲,向量v在两种情况下都是共享资源,并且如果要在创建后对其进行更改,则也应使用互斥量进行保护。 但是,这样的锁会(正确地)破坏所有并行性..因此,让我们暂时忽略它;)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM