C++ 如何在c++;11使用锁紧装置
看起来在c++17中提供了我想要的功能,但是我目前与c++11绑定在一起 目前,我看到guard_lock出现死锁问题,我们多次使用相同的互斥锁调用它。作用域_锁是否可以防止多次调用(即重新进入?)? 在c++11w/lock_-guard中有这样做的最佳实践吗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)) {
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、锁\保护常数和锁){
喝倒采