它是安全锁/范围保护实现

Is it safe lock/scope guard implementation?

本文关键字:范围 保护 实现 安全      更新时间:2023-10-16

现在我从类中获取线程安全字段的实现:

int A::GetValue() const
{
    _mutex.Lock();
    int temp = _value;
    _mutex.Unlock();
    return temp;
}

我想用这样的锁/作用域保护实现来代替它(LockGuard类只有构造函数/析构函数和Mutex * _mutex字段):

LockGuard::LockGuard(Mutex & mutex) : _mutex(&mutex)
{
    _mutex->Lock();
}
LockGuard::~LockGuard()
{
    _mutex->Unlock();
}

和重构代码:

int A::GetValue() const
{
    LockGuard lockGuard(_mutex);
    return _value;
}

我突然意识到,我不确定这是否是一个安全的实现。它是否保证首先_value的副本将被传递出函数,并且只有当这个副本已经存在时,_互斥锁才会被解锁?请不要提供c++ 11的替代实现示例-我有嵌入式系统,不幸的是不能使用它们。

这一行有问题:

LockGuard(_mutex);

应该是:

LockGuard foo(_mutex);

否则,它将超出作用域并在方法的其余部分执行之前解锁互斥锁。(您可以通过在LockGuard构造函数和析构函数以及调用方法中临时插入printf或类似的方法来验证有问题的行为)。

除此之外,你的锁模式是好的

也许这个程序可以帮助你想象发生了什么:

#include <iostream>
// Replaces the int so that we know when things happen
struct Int {
   Int() {
       std::cout << "Int::Int()" << std::endl;
   }
   ~Int() {
       std::cout << "Int::~Int()" << std::endl;
   }
   Int(const Int &x) {
       std::cout << "Int::Int(const Int&)" << std::endl;
   }
};
struct LockGuard {
   LockGuard() {
     std::cout << "Locking" << std::endl;
   }
   ~LockGuard() {
     std::cout << "Unlocking" << std::endl;
   }    
};
struct A {    
  Int getValue() const {
     LockGuard lockGuard;
     return _value;
  }    
  Int _value;    
};

int main() {
   A a;
   std::cout << "about to call" << std::endl;
   Int x=a.getValue();
   std::cout << "done calling" << std::endl;
}

结果是

Int::Int()
about to call
Locking
Int::Int(const Int&)
Unlocking
done calling
Int::~Int()
Int::~Int()

最后需要注意的是,您可能需要在属性声明中使用_mutex mutable,因为锁定和解锁通常是非const操作,否则在const方法中是不允许的

你的LockGuard的实现是好的,但使用是错误的。使用语句

LockGuard(_mutex);

您正在创建一个临时的LockGuard,它将在语句完成后被销毁。

用法应该是

LockGuard guard(_mutex);
return _value;

LockGuard guard(_mutex);将创建一个LockGuard对象,该对象将锁定构造函数中的互斥锁。当方法返回时,将调用析构函数,解锁互斥锁。并且您不再需要使用临时返回