没有网上示例生动地展示这一点。在http://en.cppreference.com/w/cpp/header/shared_mutex看到一个例子,但是 目前还不清楚。有人可以帮忙吗?
答案 0 :(得分:4)
通过使用普通的互斥锁,您可以保证对某种关键资源的独占访问 - 而不是其他任何东西。共享互斥锁通过允许两级访问来扩展此功能:共享和独占,如下所示:
典型情况是数据库:若多个线程同时读取同一个数据并不重要。但是修改数据库是至关重要的 - 如果某个线程读取数据而另一个线程正在写入,则可能会收到不一致的数据。因此,在允许写入之前必须完成所有读取,并且新读取必须等到写入完成。写完后,可以再次进行进一步的读取。
编辑:旁注:
为什么读者需要锁?
这是为了防止编写器在读取时获取锁定。此外,它还可以防止新读者获得锁定,如果它仍然是专有的。
答案 1 :(得分:2)
"共享互斥锁通常用于多个读者可以同时访问同一资源而不会导致数据争用的情况,但只有一个编写者可以这样做。"
cppreference.com
当您需要读/写锁定时,这非常有用:https://en.wikipedia.org/wiki/Readers%E2%80%93writer_lock
答案 2 :(得分:2)
共享互斥锁有两个级别的访问权限,共享'和'独家'。 多个线程可以获得共享访问权限,但只有一个可以拥有“独占”权限。访问(包括没有共享访问权限)。
常见的场景是读/写锁。回想一下,数据竞争只能在两个线程访问相同数据时才会发生,其中至少有一个是写。
许多读者可能会阅读这些数据,但是当作者需要访问时,他们必须获得对数据的独占访问权。
这是一个示例(稍微改编自http://en.cppreference.com/w/cpp/thread/shared_mutex中的示例)。
#include <iostream>
#include <mutex> // For std::unique_lock
#include <shared_mutex>
#include <thread>
std::mutex cout_mutex;
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()
返回如何显示两个线程在读取期间持有共享锁。