C++ boost::作用域锁定RAII行为

C++ boost::作用域锁定RAII行为,c++,boost,scope,mutex,scoped-lock,C++,Boost,Scope,Mutex,Scoped Lock,在容器类中,我想锁定一个boost::mutex向量,每个向量都由一个受控实例拥有(奇怪的代码设计,但仅用于MWE目的) 问题是,如果我很好地理解了RAII习惯用法和作用域锁定上下文,那么这样一来,锁定在for周期结束后不久就会超出范围 我试着在容器ctor上new一个锁数组,并在其dtor上删除它,但我想这是违反RAII习惯用法本身的 我误解了什么,或者我如何重构整个问题?假设您的问题是:“如何同时对多个互斥体使用类似RAII的作用域锁?” 然后,您可以为多个锁创建自己的RAII包装器,或者使

在容器类中,我想
锁定
一个
boost::mutex
向量,每个向量都由一个受控实例拥有(奇怪的代码设计,但仅用于MWE目的)

问题是,如果我很好地理解了RAII习惯用法和
作用域锁定
上下文,那么这样一来,锁定在
for
周期结束后不久就会超出范围

我试着在容器ctor上
new
一个锁数组,并在其dtor上
删除它,但我想这是违反RAII习惯用法本身的


我误解了什么,或者我如何重构整个问题?

假设您的问题是:“如何同时对多个互斥体使用类似RAII的作用域锁?”

然后,您可以为多个锁创建自己的RAII包装器,或者使用类似于

(未经测试的伪代码,但希望您能理解。)

模板
类多重锁定保护
{
私人:
滴定仪开始,结束;
多个锁定装置(滴定器开始,滴定器结束)
:_begin{begin},_end{end}
{
for(自动it=\u开始;it!=\u结束;++it)
{
it->_mutex.lock();
}
}
~multiple_lock_guard()
{
for(自动it=\u开始;it!=\u结束;++it)
{
它->_mutex.unlock();
}
}
};
您可以按如下方式使用它:

void Container::desired_main_method()
{
    multiple_lock_guard mlg(std::begin(_vData), std::end(_vData));

    for(int i = 0; i < _vData.size(); i++)
    {
        this->processing(i);
    }

    for(int i = 0; i < _vData.size(); i++)
    {
        this->post_processing(i);
    }
}
void容器::所需的\u主\u方法()
{
多重锁定保护mlg(std::begin(_vData),std::end(_vData));
对于(int i=0;i处理(i);
}
对于(int i=0;i后处理(i);
}
}

以下内容如何

void Container::desired_main_method()
{
  std::vector<boost::mutex::scoped_lock> locks;

  for (int i=0; i<_vData.size(); i++)
  {
    locks.emplace_back(_vData.at(i)->_mutex);
  }

  for (int i=0; i<_vData.size(); i++)
  {
    this->processing(i);
  }

  for (int i=0; i<_vData.size(); i++)
  {
    this->post_processing(i);
  }
}
void容器::所需的\u主\u方法()
{
向量锁;
for(int i=0;i_互斥);
}
对于(int i=0;i处理(i);
}
for(int i=0;ipost_处理(i);
}
}

您已经可以使用Boost Thread的免费函数扩展来自动锁定延迟锁集合:

  • 遗憾的是,c++17没有提供这种重载

#include <boost/thread.hpp>
#include <vector>

struct X {
    boost::mutex mutable mx;
};

void foo(std::vector<X> const& xs) {

    std::vector<boost::unique_lock<boost::mutex> > locks;
    for (auto& x : xs) {
        locks.emplace_back(x.mx, boost::defer_lock);
    }

    boost::lock(locks.begin(), locks.end());

    // all locks held
}

int main() {
    std::vector<X> xs(10);
    foo(xs);
}
#包括
#包括
结构X{
互斥可变mx;
};
void foo(std::vector const&xs){
向量锁;
用于(自动&x:xs){
锁定。向后放置(x.mx,boost::延迟锁定);
}
boost::lock(locks.begin(),locks.end());
//所有的锁都锁好了
}
int main(){
std::向量xs(10);
foo(xs);
}

为什么要编写自己的?标准库有很多功能(围绕
std::lock
defer\u lock\t
)。Boost通过迭代器范围接口使其功能更加强大(参见我的答案)。请注意,它将更加健壮,因为您的实现自然是死锁的-prone@sehe:公平点-我的回答旨在向OP展示如何以可应用于类似问题的通用方式解决其“多锁保护”问题,并展示如何实现自己的RAII包装器。
void Container::desired_main_method()
{
    multiple_lock_guard mlg(std::begin(_vData), std::end(_vData));

    for(int i = 0; i < _vData.size(); i++)
    {
        this->processing(i);
    }

    for(int i = 0; i < _vData.size(); i++)
    {
        this->post_processing(i);
    }
}
void Container::desired_main_method()
{
  std::vector<boost::mutex::scoped_lock> locks;

  for (int i=0; i<_vData.size(); i++)
  {
    locks.emplace_back(_vData.at(i)->_mutex);
  }

  for (int i=0; i<_vData.size(); i++)
  {
    this->processing(i);
  }

  for (int i=0; i<_vData.size(); i++)
  {
    this->post_processing(i);
  }
}
#include <boost/thread.hpp>
#include <vector>

struct X {
    boost::mutex mutable mx;
};

void foo(std::vector<X> const& xs) {

    std::vector<boost::unique_lock<boost::mutex> > locks;
    for (auto& x : xs) {
        locks.emplace_back(x.mx, boost::defer_lock);
    }

    boost::lock(locks.begin(), locks.end());

    // all locks held
}

int main() {
    std::vector<X> xs(10);
    foo(xs);
}