多线程 boost的读写(reader-writer)锁

背景:保护很少更新的数据结构时,c++标准库没有提供相应的功能。

例如:有个DNS条目缓存的map,基本上很少有更新,大部分都是读取,但是偶尔也会有更新,这种情况下,如果在读取的函数里加上std::mutex就过于悲观了,每次只能有一个线程读取,但是想要的效果是,多个线程可以同时读取。这个时候c++标准库就显得无能为力了。

boost库就能登场了。

boost有个共享锁:boost::shared_mutex和boost::shared_lock,用boost::shared_mutex代替std::mutex后,当有某一个线程读取dns时,就锁住了这个共享锁,当第二个线程也要读取时,这是第一个还没读完,也就是还没有解锁,如果用的是std::mutex的话,第二线程是无法进行读取的,但是换成boost::shared_mutex后,第二个线程也可以读取了,即便第一个读取的线程还有结束。

但是也有限制,读取操作可以多个线程同时读取,但是某个时间点,有个线程要更新dns,是否可以更新取决于,这个时间点是否有读的线程还没有结束。

1,如果读取的线程都结束了,也就是所有的共享锁都被解锁了,这时可以更新dns,并且在更新的同时,所有读取的线程都要被阻塞;

2,如果读取的线程还有任意一个没有结束了,也就是说并不是所有的共享锁都被解锁了,这时,更新的线程就会被阻塞,直到,所有的读取线程结束后,更新线程才会开始。

例子:

#include <map>
#include <string>
#include <thread>
#include <mutex>
#include <functional>
#include <boost/thread/shared_mutex.hpp> class dns_entry{ };
class dns_cache{
std::map<std::string, dns_entry> entries;
mutable boost::shared_mutex entry_mutex;
public:
dns_entry find_entry(std::string const& domain)const{
boost::shared_lock<boost::shared_mutex> lk(entry_mutex);
std::map<std::string, dns_entry>::const_iterator const it =
entries.find(domain);
return (it == entries.end()) ? dns_entry() : it->second;
}
void update_or_add_entry(std::string const& domain, dns_entry const& dns_details){
std::lock_guard<boost::shared_mutex> lk(entry_mutex);
entries[domain] = dns_details;
}
};
int main(){
dns_entry de;
dns_cache cache1, cache2, cache3;
std::thread t(&dns_cache::find_entry, std::ref(cache3), "aaa");
t.join();
std::thread t1(&dns_cache::update_or_add_entry, std::ref(cache1), "aaa", de);
t1.join();
std::thread t2(&dns_cache::find_entry, std::ref(cache2), "aaa");
t2.join();
}

github源代码

编译方法:

g++ -g boost-shared-mutex.3.13.cpp -std=c++11 -L/home/ys/Downloads/boost_1_68_0/stage/lib -lboost_thread -lboost_system -pthread

编译或者运行有问题的,请参考多线程 boost编译与运行的坑

小知识点:

1,下面的&X::open_connection的用法,必须有&和this,虽然open_connection的参数列表为空。因为open_connection是类的成员方法,所以就必须绑定到这个类的某个具体对象上,所以才必须有this和&。&是为了告诉编译器,这个方法不是类的static方法,而是类的成员方法。

2,std::ref(cache1),必须加上std::ref,否则编译不通过。原因:如果不使用std::ref,就会复制一个cache1,这明显不是想要的结果,想要的就是cache1,和bind函数原理一样。

std::thread t1(&dns_cache::update_or_add_entry, std::ref(cache1), "aaa", de);

c/c++ 学习互助QQ群:877684253

本人微信:xiaoshitou5854

c/c++ 多线程 boost的读写(reader-writer)锁的更多相关文章

  1. 系统学习 Java IO (十五)----字符读写 Reader/Writer 其他子类

    目录:系统学习 Java IO---- 目录,概览 跟踪行号的缓冲字符输入流 LineNumberReader LineNumberReader 类是一个 BufferedReader ,用于跟踪读取 ...

  2. 系统学习 Java IO (十三)----字符读写 Reader/Writer 及其常用子类

    目录:系统学习 Java IO---- 目录,概览 Reader Reader 类是 Java IO API 中所有 Reader 子类的基类. Reader 类似于 InputStream ,除了它 ...

  3. RFID 读写器 Reader Writer Cloner

    RFID读写器的工作原理 RFID的数据采集以读写器为主导,RFID读写器是一种通过无线通信,实现对标签识别和内存数据的读出和写入操作的装置. 读写器又称为阅读器或读头(Reader).查询器(Int ...

  4. Stream,Reader/Writer,Buffered的区别(1)

    Stream: 是字节流形式,exe文件,图片,视频等.支持8位的字符,用于 ASCII 字符和二进制数据. Reader/Writer: 是字符流,文本文件,XML,txt等,用于16位字符,也就是 ...

  5. RFIDler - An open source Software Defined RFID Reader/Writer/Emulator

    https://www.kickstarter.com/projects/1708444109/rfidler-a-software-defined-rfid-reader-writer-emul h ...

  6. RubyMine生成reader/writer方法

    RubyMine生成reader/writer方法 在非类的ruby文件中,Alt+Insert会出现新建文件的选项: 在ruby文件的类中,Alt+Insert会出现get/set方法生成提示和重构 ...

  7. [多线程] 线程中的synchronized关键字锁

    为什么要用锁? 在多线程中,难免会出现在多个线程中对同一个对象的实例变量或者全局静态变量进行并发访问的情况,如果不做正确的同步处理,那么产生的后果就是"脏读",也就是取到的数据其实 ...

  8. “全栈2019”Java多线程第二十八章:公平锁与非公平锁详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  9. Java多线程(五) —— 线程并发库之锁机制

    参考文献: http://www.blogjava.net/xylz/archive/2010/07/08/325587.html 一.Lock与ReentrantLock 前面的章节主要谈谈原子操作 ...

随机推荐

  1. 花点时间顺顺Git(上)

    花点时间顺顺Git(上) 为了让你们点进来贼努力的想了一个色彩斑斓大吉大利的标题,好,看正文 历史:Linus的作者创建了开源的Linux,02年以前代码管理都依赖手动合并,后来管理不了了,拒绝SVN ...

  2. 【Docker】(4)搭建私有镜像仓库

    [Docker](4)搭建私有镜像仓库 说明 1. 这里是通过阿里云,搭建Docker私有镜像仓库. 2. 这里打包的镜像是从官网拉下来的,并不是自己项目创建的新镜像,主要测试功能 一.搭建过程 首先 ...

  3. VM14安装Mas os 13

      工具/原料   VMware Workstation unlocker(for OS X 插件补丁) macOS 10.13镜像 vmware tools 安装前准备   1 下载以上文件: 1. ...

  4. sql server 性能调优之 SQL语句阻塞查询

    在生产环境下,有时公司客服反映网页半天打不到,除了在浏览器按F12的Network响应来排查,确定web服务器无故障后.就需要检查数据库是否有出现阻塞 当时数据库的生产环境中主表数据量超过2000w, ...

  5. Python爬虫入门教程 26-100 知乎文章图片爬取器之二

    1. 知乎文章图片爬取器之二博客背景 昨天写了知乎文章图片爬取器的一部分代码,针对知乎问题的答案json进行了数据抓取,博客中出现了部分写死的内容,今天把那部分信息调整完毕,并且将图片下载完善到代码中 ...

  6. Android创建或删除了文件,在电脑端查看的时候,却没有对应的变化,处理办法

    在Android应用中,碰到一个问题,在代码中执行创建或者删除某个文件后,在系统的文件管理器中能够相应地看到文件的变化,但是插在电脑上查看的时候,却看不到改文件的变化.同时,当创建文件后,在系统中的某 ...

  7. 用户身份切换之初窥企业远程用户没root还有root权限

    一直很困扰我,既然企业不让用root不能登录,那怎么操作文件呢? 原来...... su -    用来切换初始变量 $PATH $HOME等 sudo 用的时候会su到root需要root的密码,这 ...

  8. Docker系列01—容器的发展历程---Docker的生态圈

    本文收录在容器技术学习系列文章总目录 Docker 和容器技术的发展可谓是日新月异,本文试图以全局的视角来梳理一下 docker 目前的生态圈.既然是概览,所以不会涉及具体的技术细节. Docker ...

  9. redis常见错误处理

    --1]当内存不足引起  redis出错 先尝试下列语句,指定redis使用内存 redis-server.exe redis.windows.conf --maxheap 200mredis-ser ...

  10. WPF TextBox/TextBlock 文本超出显示时,文本靠右显示

    文本框显示 文本框正常显示: 文本框超出区域显示: 实现方案 判断文本框是否超出区域 请见<TextBlock IsTextTrimmed 判断文本是否超出> 设置文本布局显示 1. Fl ...