Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/144.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何在c++;11使用锁紧装置_C++_C++11 - Fatal编程技术网

C++ 如何在c++;11使用锁紧装置

C++ 如何在c++;11使用锁紧装置,c++,c++11,C++,C++11,看起来在c++17中提供了我想要的功能,但是我目前与c++11绑定在一起 目前,我看到guard_lock出现死锁问题,我们多次使用相同的互斥锁调用它。作用域_锁是否可以防止多次调用(即重新进入?)? 在c++11w/lock_-guard中有这样做的最佳实践吗 mutex lockingMutex; void get(string s) { lock_guard<mutex> lock(lockingMutex); if (isPresent(s)) {

看起来在c++17中提供了我想要的功能,但是我目前与c++11绑定在一起

目前,我看到guard_lock出现死锁问题,我们多次使用相同的互斥锁调用它。作用域_锁是否可以防止多次调用(即重新进入?)? 在c++11w/lock_-guard中有这样做的最佳实践吗

mutex lockingMutex;

void get(string s)
{
    lock_guard<mutex> lock(lockingMutex);
    if (isPresent(s))
    {
        //....
    }
}

bool isPresent(string s)
{
    bool ret = false;
    lock_guard<mutex> lock(lockingMutex);
    //....
    return ret;
}
mutex锁定mutex;
void get(字符串s)
{
锁\防护锁(锁定互斥锁);
如果(显示)
{
//....
}
}
bool isPresent(字符串s)
{
bool-ret=假;
锁\防护锁(锁定互斥锁);
//....
返回ret;
}

能够多次锁定需要使用的同一互斥锁。递归互斥比非递归互斥代价更高

不过,最好的做法是,在设计代码时,线程不会多次锁定同一互斥锁。例如,让公共函数先锁定互斥体,然后调用预期互斥体已被锁定的实现函数。实现函数不能调用锁定互斥锁的公共API函数。例如:

class A {
    std::mutex m_;
    int state_ = 0;

private: // These expect the mutex to have been locked.
    void foo_() {
        ++state_;
    }

    void bar_() {
        this->foo_();
    }

public: // Public functions lock the mutex first.
    void foo() {
        std::lock_guard<std::mutex> lock(m_);
        this->foo_();
    }

    void bar() {
        std::lock_guard<std::mutex> lock(m_);
        this->bar_();
    }
};
A类{
std::互斥m_;
int状态=0;
private://这些期望互斥锁已被锁定。
void foo_uz(){
++州政府;
}
空条(){
这个->foo_();
}
public://public函数首先锁定互斥锁。
void foo(){
标准:锁和防护锁(m);
这个->foo_();
}
空条(){
标准:锁和防护锁(m);
这个->条();
}
};

能够多次锁定需要使用的同一互斥锁。递归互斥比非递归互斥代价更高

不过,最好的做法是,在设计代码时,线程不会多次锁定同一互斥锁。例如,让公共函数先锁定互斥体,然后调用预期互斥体已被锁定的实现函数。实现函数不能调用锁定互斥锁的公共API函数。例如:

class A {
    std::mutex m_;
    int state_ = 0;

private: // These expect the mutex to have been locked.
    void foo_() {
        ++state_;
    }

    void bar_() {
        this->foo_();
    }

public: // Public functions lock the mutex first.
    void foo() {
        std::lock_guard<std::mutex> lock(m_);
        this->foo_();
    }

    void bar() {
        std::lock_guard<std::mutex> lock(m_);
        this->bar_();
    }
};
A类{
std::互斥m_;
int状态=0;
private://这些期望互斥锁已被锁定。
void foo_uz(){
++州政府;
}
空条(){
这个->foo_();
}
public://public函数首先锁定互斥锁。
void foo(){
标准:锁和防护锁(m);
这个->foo_();
}
空条(){
标准:锁和防护锁(m);
这个->条();
}
};

作用域锁无法提供您所需的功能

作用域锁只是锁防护的一个变量版本。它只存在于将锁保护更改为变量模板时出现的一些ABI问题

要拥有可重入互斥体,您需要使用可重入互斥体。但这在运行时代价更高,并且通常表明在互斥状态下缺乏关心。持有互斥锁时,您应该完全了解正在执行的所有其他同步操作

一旦您完全了解了正在执行的所有同步操作,就很容易避免递归锁定

这里有两种模式可以考虑。首先,将公共锁定API与私有非锁定API分离。第二,从实现中分离同步

private:
  mutex lockingMutex;
  bool isPresent(string s, lock_guard<mutex> const& lock) {
    bool ret = false;
    //....
    return ret;
  }
  void get(string s, lock_guard<mutex> const& lock) {
    if (isPresent(s, lock))
    {
      //....
    }
  }
public:  
  void get(string s) {
    return get( std::move(s), lock_guard<mutex>(lockingMutex) );
  }

  bool isPresent(string s) {
    return isPresent( std::move(s), lock_guard<mutex>(lockingMutex) );
  }
};
private:
互斥锁;
bool isPresent(字符串s、锁\保护常数和锁){
bool-ret=假;
//....
返回ret;
}
无效获取(字符串s、锁\保护常数和锁){
如果(显示,锁定))
{
//....
}
}
公众:
void get(字符串s){
返回get(std::move(s),lock_-guard(lockingMutex));
}
bool isPresent(字符串s){
返回isPresent(std::move(s),lock_guard(lockingMutex));
}
};
这里我用锁作为“我们有锁的证据”

更好的选择是将类编写为非线程安全的,然后使用包装器:

template<class T>
struct mutex_guarded {
  template<class T0, class...Ts,
    std::enable_if_t<!std::is_same<std::decay_t<T0>, mutex_guarded>{}, bool> =true
  >
  mutex_guarded(T0&&t0, Ts&&...ts):
    t( std::forward<T0>(t0), std::forward<Ts>(ts)... )
  {}
  mutex_guarded()=default;
  ~mutex_guarded=default;

  template<class F>
  auto read( F&& f ) const {
    auto l = lock();
    return f(t);
  }
  template<class F>
  auto write( F&& f ) {
    auto l = lock();
    return f(t);
  }
private:
  auto lock() { return std::unique_lock<std::mutex>(m); }
  auto lock() const { return std::unique_lock<std::mutex>(m); }
  mutable std::mutex m;
  T t;
};    
模板
结构互斥锁{
模板{},bool>=true
>
受保护的互斥(T0&&T0,Ts&&Ts):
t(标准:正向(t0),标准:正向(ts)…)
{}
mutex_guarded()=默认值;
~mutex_guarded=默认值;
样板
自动读取(F&&F)常数{
自动l=锁定();
返回f(t);
}
样板
自动写入(F&&F){
自动l=锁定();
返回f(t);
}
私人:
auto lock(){return std::unique_lock(m);}
auto lock()常量{return std::unique_lock(m);}
可变std::mutexm;
T;
};    
现在我们可以这样使用:

mutex_guarded<Foo> foo;
foo.write([&](auto&&foo){ foo.get("hello"); } );
互斥锁;
foo.write([&](auto&&foo){foo.get(“hello”);});
您可以编写
mutex\u-gaurded
共享的mutex\u-guarded
非mutex\u-guarded
甚至
异步的mutex\u-guarded
(返回工作线程中的未来和序列化操作)


只要类没有在方法中留下自己的“控制区”,这种模式就可以更轻松地编写互斥保护数据,并允许您将相关的互斥保护数据组合到一个包中,而无需重写它们。

作用域锁不会提供您所需的功能

作用域锁只是锁防护的一个变量版本。它只存在于将锁保护更改为变量模板时出现的一些ABI问题

要拥有可重入互斥体,您需要使用可重入互斥体。但这在运行时代价更高,并且通常表明在互斥状态下缺乏关心。持有互斥锁时,您应该完全了解正在执行的所有其他同步操作

一旦您完全了解了正在执行的所有同步操作,就很容易避免递归锁定

这里有两种模式可以考虑。首先,将公共锁定API与私有非锁定API分离。第二,从实现中分离同步

private:
  mutex lockingMutex;
  bool isPresent(string s, lock_guard<mutex> const& lock) {
    bool ret = false;
    //....
    return ret;
  }
  void get(string s, lock_guard<mutex> const& lock) {
    if (isPresent(s, lock))
    {
      //....
    }
  }
public:  
  void get(string s) {
    return get( std::move(s), lock_guard<mutex>(lockingMutex) );
  }

  bool isPresent(string s) {
    return isPresent( std::move(s), lock_guard<mutex>(lockingMutex) );
  }
};
private:
互斥锁;
bool isPresent(字符串s、锁\保护常数和锁){
喝倒采