class LocalRouteProvider {
private:
std::mutex localization_state_lock_;
bool localization_state_ = false;
};
- std::mutex 是 C++ 标准库中提供的一个互斥锁类。
互斥锁
(Mutex,Mutual Exclusion)是一种同步原语,用于保护共享资源,防止多个线程同时访问和修改同一资源
,从而避免数据竞争和不一致的问题 - localization_state_lock_ 是std::mutex 类型的 对象。这个对象可以在
多线程环境
中用来保护对某个共享资源(例如 localization_state_)的访问
如何使用localization_state_lock_
呢?
答:为了确保线程安全,你需要在访问共享资源时正确地使用互斥锁。通常的做法是使用 std::lock_guard 或 std::unique_lock 来自动管理互斥锁的锁定和解锁
示例:使用 std::lock_guard,如下所示:
class LocalRouteProvider {
private:
std::mutex localization_state_lock_; // 互斥锁,保护 localization_state_
bool localization_state_ = false; // // 定位状态
public:
void SetLocalizationState(bool state) {
std::lock_guard<std::mutex> lock(localization_state_lock_);
localization_state_ = state;
}
bool GetLocalizationState() const {
std::lock_guard<std::mutex> lock(localization_state_lock_);
return localization_state_;
}
};
解释如下:
SetLocalizationState 方法:
std::lock_guard<std::mutex> lock(localization_state_lock_);:这行代码创建了
一个 std::lock_guard 对象,它会在构造时自动锁定 localization_state_lock_ 互斥锁。
localization_state_ = state;:在这行代码执行期间,互斥锁已经锁定,其他线程不能同时
访问localization_state_。
当 **lock 对象超出作用域**时,**std::lock_guard** 会自动释放互斥锁。
GetLocalizationState 方法:
同样的,std::lock_guard<std::mutex> lock(localization_state_lock_);
会在构造时自动锁定互斥锁。
return localization_state_;:在这行代码执行期间,互斥锁已经锁定,
其他线程不能同时访问 localization_state_。
当 lock 对象超出作用域时,std::lock_guard 会自动释放互斥锁
疑问:这个lock 对象超出作用域时,std::lock_guard 会自动释放互斥锁,怎么理解?
理解 std::lock_guard 如何在超出作用域时自动释放互斥锁是理解 C++ 中 RAII(Resource Acquisition Is Initialization,资源获取即初始化)原则的关键。让我们详细解释一下这个过程。
- RAII 原则
RAII 是一种编程范式,通过对象的生命周期管理资源的获取和释放。在 C++ 中,这意味着资源(如内存、文件句柄、互斥锁等)在对象构造时获取,在对象析构时释放。
- std::lock_guard 的作用
std::lock_guard 是一个简单的 RAII 类,用于管理互斥锁的锁定和解锁。它的主要特点如下:
构造函数:在 std::lock_guard 对象被创建时,它会自动调用互斥锁的 lock() 方法,锁定互斥锁。
析构函数:在 std::lock_guard 对象超出作用域时(即对象被销毁时),
它会自动调用互斥锁的 unlock() 方法,释放互斥锁。
- 代码示例
让我们再次看一下 SetLocalizationState 方法的实现
#include <mutex>
class LocalRouteProvider {
private:
std::mutex localization_state_lock_; // 互斥锁,保护 localization_state_
bool localization_state_ = false; // 定位状态
public:
// 设置定位状态
void SetLocalizationState(bool state) {
std::lock_guard<std::mutex> lock(localization_state_lock_);
localization_state_ = state;
}
};
详细解释如下:
1)创建 std::lock_guard 对象:
std::lock_guard<std::mutex> lock(localization_state_lock_);
这行代码创建了一个 std::lock_guard 对象 lock,并将 localization_state_lock_ 作为参数传入。在 std::lock_guard 的构造函数中,localization_state_lock_ 会被自动锁定。
2)访问共享资源:
localization_state_ = state;
这行代码在互斥锁已经锁定的情况下,安全地修改 localization_state_。
此时,其他线程无法访问 localization_state_,因为互斥锁已经被当前线程持有。
3) 超出作用域:
当 SetLocalizationState 方法执行完毕,控制流离开该方法时,lock 对象会超出其作用域。在 lock 对象的析构函数中,localization_state_lock_ 会被自动解锁。
4) 作用域和析构
作用域:**lock 对象的作用域是 SetLocalizationState 方法的整个函数体**
。当函数返回时,
lock 对象的生命期结束。
析构函数:std::lock_guard 的析构函数会自动调用 localization_state_lock_ 的 unlock()
方法, 释放互斥锁。
5) 代码执行流程
进入 SetLocalizationState 方法:
创建 std::lock_guard 对象 lock,锁定 localization_state_lock_。
修改 localization_state_:
执行 localization_state_ = state;,安全地修改 localization_state_。
离开 SetLocalizationState 方法:
lock 对象超出作用域,调用 std::lock_guard 的析构函数。
析构函数调用 localization_state_lock_ 的 unlock() 方法,释放互斥锁
总结:
std::lock_guard 通过 RAII 原则自动管理互斥锁的锁定和解锁。当 std::lock_guard 对象超出作用域时,它会自动释放互斥锁,确保资源的正确管理和线程安全。这种方式不仅简洁,而且减少了手动管理锁带来的错误风险