C ++中的(共享)互斥锁

Ben*_* C. 4 c++ multithreading mutex thread-safety c++17

我看过一个共享互斥锁的例子:

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 ...
    }
};
Run Code Online (Sandbox Code Playgroud)

我自然会写:

public:
    void write() {
        mut_.lock();
        // ... write to data_ ...
        mut_.unlock();
    }

    void read() const {
        mut_.lock_shared();
        // ... read the data ...
        mut_.unlock_shared();
    }
};
Run Code Online (Sandbox Code Playgroud)

我的方法也对吗?我使用的内容与示例中使用的内容之间有区别吗?另外,一个比另一个有优势吗?谢谢!

眠りネ*_*ネロク 11

我的方法也对吗?

考虑如果互斥锁锁定和解锁之间的代码抛出异常会发生什么:

void write() {
    mut_.lock();
    // <-- exception is thrown here
    mut_.unlock();
}
Run Code Online (Sandbox Code Playgroud)

然后互斥锁保持锁定状态。

一个比另一个有优势吗?

是的,unique_lock<>遵循RAII idiom,因此在发生异常时会自动处理互斥锁的解锁(即,由其析构函数):

void write() {
    unique_lock<shared_mutex> lk(mut_);
    // <-- exception is thrown
}
Run Code Online (Sandbox Code Playgroud)

如果在创建unique_lock<shared_mutex>对象后发生异常– lk– 调用其析构函数,然后如果它被锁定,则解锁关联的互斥锁(请记住std::unique_lock,与 不同std::lock_guard,并不总是拥有关联互斥锁的所有权 – 请参阅std::defer_lockstd::unique_lock::unlock())。

综上所述,随着lock_guard/ unique_lock/ shared_lock,没有特殊的处理是从你身边在例外的情况下,或离开由不同的执行路径的成员函数时需要。

  • @BenC。它会自动解锁互斥体——如果它被锁定,在你的情况下,它是——在销毁时,当“lk”被销毁时。我建议您也看看 [`std::lock_guard`](https://en.cppreference.com/w/cpp/thread/lock_guard)。`std::unique_lock` 更灵活,但看起来不需要这种灵活性。 (4认同)

art*_*rtm 5

通常避免使用原始互斥锁,而使用 RAII 版本 unique_lock(),这在两种情况下更安全:

  • 例外
  • 过早回归

像原始指针一样,通常会避免使用 RAII 版本的智能指针:unique_ptr 或 shared_ptr。

无论哪种情况,RAII 版本都确保互斥锁(或指针)在超出范围时始终被释放。