网上还没有例子来生动地演示这一点。在 http://en.cppreference.com/w/cpp/header/shared_mutex 看到了一个例子,但是 目前还不清楚。有人可以帮忙吗?
通过使用普通的互斥体,您可以保证对某种关键资源的独占访问——仅此而已。共享互斥体通过允许两个级别的访问来扩展此功能:共享和独占,如下所示:
旁注:
为什么读者需要锁?这是为了防止写入者在读取时获取锁。此外,如果锁仍以独占方式持有,它会阻止新的读者获取锁。
常见的场景是读/写锁。回想一下,只有当两个线程访问相同的数据
其中至少一个是写入时,才会发生数据争用。 共享互斥体的优点是数据可以被许多读取器读取,但是当写入器需要访问时,他们必须获得对数据的独占访问权。
为什么两者都有?一方面,排他锁构成了一个普通的互斥体,因此可以说只需要共享。但共享锁实现中可能存在一些开销,可以使用功能较少的类型来避免这些开销。
这是一个示例(稍微改编自此处的示例
http://en.cppreference.com/w/cpp/thread/shared_mutex)。
#include <iostream>
#include <mutex>
#include <shared_mutex>
#include <thread>
std::mutex cout_mutex;//Not really part of the example...
void log(const std::string& msg){
std::lock_guard guard(cout_mutex);
std::cout << msg << std::endl;
}
class ThreadSafeCounter {
public:
ThreadSafeCounter() = default;
// Multiple threads/readers can read the counter's value at the same time.
unsigned int get() const {
std::shared_lock lock(mutex_);//NB: std::shared_lock will shared_lock() the mutex.
log("get()-begin");
std::this_thread::sleep_for(std::chrono::milliseconds(500));
auto result=value_;
log("get()-end");
return result;
}
// Only one thread/writer can increment/write the counter's value.
void increment() {
std::unique_lock lock(mutex_);
value_++;
}
// Only one thread/writer can reset/write the counter's value.
void reset() {
std::unique_lock lock(mutex_);
value_ = 0;
}
private:
mutable std::shared_mutex mutex_;
unsigned int value_ = 0;
};
int main() {
ThreadSafeCounter counter;
auto increment_and_print = [&counter]() {
for (int i = 0; i < 3; i++) {
counter.increment();
auto ctr=counter.get();
{
std::lock_guard guard(cout_mutex);
std::cout << std::this_thread::get_id() << ' ' << ctr << '\n';
}
}
};
std::thread thread1(increment_and_print);
std::thread thread2(increment_and_print);
std::thread thread3(increment_and_print);
thread1.join();
thread2.join();
thread3.join();
}
可能的部分输出:
get()-begin
get()-begin
get()-end
140361363867392 2
get()-end
140361372260096 2
get()-begin
get()-end
140361355474688 3
//Etc...
注意两个
get()-begin()
返回如何显示两个线程在读取期间持有共享锁。