Ana*_*rni 2 c++ multithreading c++11
网上没有示例可以生动地演示这一点。在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();
}
Run Code Online (Sandbox Code Playgroud)
可能的部分输出:
get()-begin
get()-begin
get()-end
140361363867392 2
get()-end
140361372260096 2
get()-begin
get()-end
140361355474688 3
//Etc...
Run Code Online (Sandbox Code Playgroud)
请注意两个get()-begin()返回如何显示两个线程在读取期间持有共享锁。