C++ 中的(共享)互斥体
(Shared) mutex in C++
我看过共享互斥体的示例:
class MyData {
std::vector<double> data_;
mutable shared_mutex mut_; // the mutex to protect data_;
public:
void write() {
unique_lock<shared_mutex> lk(mut_);
// ... write to data_ ...
}
void read() const {
shared_lock<shared_mutex> lk(mut_);
// ... read the data ...
}
};
自然我会写成:
public:
void write() {
mut_.lock();
// ... write to data_ ...
mut_.unlock();
}
void read() const {
mut_.lock_shared();
// ... read the data ...
mut_.unlock_shared();
}
};
我的方法是否也正确?我使用的和示例中使用的有区别吗?另外,一个比另一个有优势吗?谢谢!
Is my way also correct?
考虑如果互斥锁的锁定和解锁之间的代码抛出异常会发生什么:
void write() {
mut_.lock();
// <-- exception is thrown here
mut_.unlock();
}
然后互斥锁保持锁定状态。
are there advantages of one over the other?
是的,unique_lock<>
在 RAII idiom 之后,因此在出现异常时自动处理互斥体的解锁(即由其析构函数处理):
void write() {
unique_lock<shared_mutex> lk(mut_);
// <-- exception is thrown
}
如果在创建 unique_lock<shared_mutex>
对象后发生异常 – lk
– 调用其析构函数,然后解锁关联的互斥锁(如果它被锁定)(记住 std::unique_lock
,与 std::lock_guard
不同,并不总是拥有关联互斥体上的锁的所有权——请参阅 std::defer_lock
and std::unique_lock::unlock()
)。
综上所述,使用lock_guard
/unique_lock
/shared_lock
,在出现异常或从不同执行路径离开成员函数时,您不需要进行特殊处理.
RAII 版本 unique_lock() 通常会避免原始互斥锁,这在两种情况下更安全:
- 异常
- 过早return
一般会避免使用原始指针,而使用 RAII 版本的智能指针:unique_ptr 或 shared_ptr。
无论哪种情况,RAII 版本都确保互斥量(或指针)在超出范围时始终被释放。
我看过共享互斥体的示例:
class MyData {
std::vector<double> data_;
mutable shared_mutex mut_; // the mutex to protect data_;
public:
void write() {
unique_lock<shared_mutex> lk(mut_);
// ... write to data_ ...
}
void read() const {
shared_lock<shared_mutex> lk(mut_);
// ... read the data ...
}
};
自然我会写成:
public:
void write() {
mut_.lock();
// ... write to data_ ...
mut_.unlock();
}
void read() const {
mut_.lock_shared();
// ... read the data ...
mut_.unlock_shared();
}
};
我的方法是否也正确?我使用的和示例中使用的有区别吗?另外,一个比另一个有优势吗?谢谢!
Is my way also correct?
考虑如果互斥锁的锁定和解锁之间的代码抛出异常会发生什么:
void write() {
mut_.lock();
// <-- exception is thrown here
mut_.unlock();
}
然后互斥锁保持锁定状态。
are there advantages of one over the other?
是的,unique_lock<>
在 RAII idiom 之后,因此在出现异常时自动处理互斥体的解锁(即由其析构函数处理):
void write() {
unique_lock<shared_mutex> lk(mut_);
// <-- exception is thrown
}
如果在创建 unique_lock<shared_mutex>
对象后发生异常 – lk
– 调用其析构函数,然后解锁关联的互斥锁(如果它被锁定)(记住 std::unique_lock
,与 std::lock_guard
不同,并不总是拥有关联互斥体上的锁的所有权——请参阅 std::defer_lock
and std::unique_lock::unlock()
)。
综上所述,使用lock_guard
/unique_lock
/shared_lock
,在出现异常或从不同执行路径离开成员函数时,您不需要进行特殊处理.
RAII 版本 unique_lock() 通常会避免原始互斥锁,这在两种情况下更安全:
- 异常
- 过早return
一般会避免使用原始指针,而使用 RAII 版本的智能指针:unique_ptr 或 shared_ptr。
无论哪种情况,RAII 版本都确保互斥量(或指针)在超出范围时始终被释放。