在C++中,std::scoped_lock(C++17引入)和std::lock_guard(C++11引入)是RAII(
Resource Acquisition Is Initialization)风格的封装器,它们会在构造时自动锁定
互斥量(mutex),并在析构时自动解锁。这些封装器确实需要知道它们将管理哪种类型
的互斥量,因为不同类型的互斥量可能有不同的接口和语义。
std::scoped_lock和std::lock_guard都模板化了它们所管理的互斥量类型,所以你需要
为它们指定类型。然而,在大多数情况下,你确实知道你要使用哪种类型的互斥量,并
且直接指定类型是很自然的。
但是,如果你想要一种更灵活的方式来处理不同类型的互斥量,你可以考虑使用std::u
nique_lock(C++11引入),它提供了更多的控制,包括延迟锁定、条件解锁等。std::
unique_lock同样模板化了它所管理的互斥量类型,但你可以通过基类指针或引用来管理
不同类型的互斥量。
然而,请注意,std::recursive_mutex的使用通常应该避免,因为它可能引入难以跟踪
和调试的复杂性和潜在问题。如果可能的话,最好重新设计你的代码以消除对递归互斥
量的需求。
对于std::shared_mutex,它是为了支持多个读者(shared locks)和一个写者(uniqu
e lock)而设计的。因此,它与std::scoped_lock、std::lock_guard和std::unique_l
ock的用法略有不同。你应该使用std::shared_lock来管理共享锁,而使用std::unique
_lock(或std::lock_guard,如果你不需要额外的控制)来管理独占锁。
最后,如果你发现自己在多个地方都需要指定互斥量的类型,并且这变得繁琐,那么你
可能需要考虑重新组织你的代码或设计,以便更简洁地管理互斥量。例如,你可以使用
类型别名(type aliases)来简化代码中的类型名称,或者将互斥量的管理封装在专门
的类或函数中。
【 在 z16166 的大作中提到: 】
std:scoped_lock<T>或者std:lock_guard<T>,在每次声明时需要指定T类型。
然而,
1、有的地方用std::mutex。
2、有的地方std::recursive_mutex(虽然这个可以通过合理的设计消除掉recursive的需求)。
3、用std::shared_mutex的倒好说,因为这个要用std::shared_lock、std::unique_lock,不搭配std::scoped_lock用。
也就是说,每次加锁/解锁时都要指明到底是std::mutex,还是std::recursive_mutex,还是很繁琐的。
目前能想到的稍微懒人点的写法,是:
std::mutex m_lock;
std::scoped_lock<decltype(m_lock)> guard1{m_lock};
std::recursive_mutex m_rlock;
std::scoped_lock<decltype(m_rlock)> guard2{m_rlock};
还有没更懒人点的写法,不用指定T的类型的?
--
FROM 124.193.189.*