共享的静音和静音之间的差异(为什么两者都存在于C 17中)
Difference between shared mutex and mutex (why do both exist in C++ 17)?
没有在线示例生动地证明这一点。在http://en.cppreference.com/w/cpp/header/shared_mutex上看到了一个示例仍然不清楚。有人可以帮忙吗?
通过使用普通静音,您可以保证对某种关键资源的独家访问,而别无其他。共享的静音通过允许两个级别的访问来扩展此功能:共享和独家,如下:
- 独家访问可以防止其他任何其他线程获得静音,就像普通的静音一样。其他线程是否试图获取共享或独家访问都没关系。
- 共享访问允许多个线程获取sutex,但仅在共享模式下它们的全部。直到所有先前的共享持有人都返回了Mutex之前,才获得独家访问(通常,只要独家请求等待,新共享的请求就会排队以在之后授予独家访问权限)。/li>
一个典型的方案是一个数据库:同时读取一个线程的几个线程是否无关紧要。但是,对数据库的修改至关重要 - 如果某些线程读取数据而另一个线程正在编写数据,则可能会收到不一致的数据。因此,所有阅读都必须在允许写作之前完成,并且必须等待新阅读才能完成。写作后,可能会再次同时发生。
编辑: sidenote:
为什么读者需要锁?
这是为了防止作者在阅读时获取锁。此外,它可以防止新的读者获得锁定尚未持有的锁。
共享的互联克具有两个级别的访问'共享'和"独家"。多个线程可以获取共享访问,但只有一个可以保留"独家"访问(其中包括没有共享访问)。
常见的情况是读/写锁。回想一下,只有当两个线程访问相同的数据至少一个是写入。
时,才能发生数据竞赛这是数据的优点可能是许多读者可以读取的,但是当作者需要访问时,他们必须获得对数据的独家访问。
为什么两者都有?一方面,独家锁构成了普通的静音,因此可以说只有共享。但是,可以使用较少的特色类型来避免共享锁定实现中的开销。
这是一个示例(从此处的示例稍微改编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()
返回如何显示两个线程在读取过程中持有共享锁。
"共享的sutexes通常在多个读者可以同时访问相同资源而不会引起数据竞赛的情况下使用,但只有一个作者可以这样做。"
>cppreference.com
当您需要阅读/作者锁时,这很有用:https://en.wikipedia.org/wiki/wiki/readers–Writer_lock
- 当两者都调用时,删除和析构函数之间的区别?
- C++类:virtual和override,或者两者都没有
- 无符号 int 与无符号长 两者都是 32 位,但我无法在不转换的情况下混合它们......为什么?
- 带大小参数和不带大小参数的"运算符删除":当两者都可用时,选择哪一个?
- 将字符串转换为整数。为什么会出现此错误?我想将 ID(字符串)更改为 IC(整数)。两者都是数组。顺便说一句,我仍然是初学者
- 无限循环与无限递归.两者都未定义吗?
- 共享的静音和静音之间的差异(为什么两者都存在于C 17中)
- x&=y 是否等同于 x = x &&y 如果两者都是 c++ 布尔值
- 两种模板类型的sizeof,当两者都是从一个基派生时
- 如果其中一个为真,则 && 结束循环,而不是如果两者都为真
- 如何编写两个初始化操作(一个作为默认初始化,另一个作为用户输入)?两者都是类的构造函数C++
- 要检查它是完整的二叉树还是完全二叉树,或者两者都不是
- 试图使用模数或fmod,但两者都给我的程序带来了问题
- 编译 SkyFireEMU 错误,sizeof(void *) 两者都不是
- 类将自身传递给其他类的构造函数,两者都使用模板定义
- 顶级或低级常量,或者两者都不存在
- 从一个模板类转换到另一个(两者都派生自同一基类)
- 我应该使用virtual, override,还是两者都使用?
- 如何从另一个文件中调用与另一个文件中同名的函数(当两者都包含时)
- 当两者都是普通char类型时,为什么is_base_of会失败?