C++ 并发编程学习(九)

作者 : 开心源码 本文共1965个字,预计阅读时间需要5分钟 发布时间: 2022-05-12 共183人阅读

保护共享数据的替代设备

一. std::once_flag 和 std::call_once

std::shared_ptr<some_resource> resource_ptr;std::once_flag resource_flag; // 1void init_resource(){    resource_ptr.reset(new some_resource);}void foo(){    std::call_once(resource_flag,init_resource); // 可以完整的进行一次初始化    resource_ptr->do_something();}

二. 一个 std::call_once 的替代方案

class my_class;my_class& get_my_class_instance(){    static my_class instance; // 线程安全的初始化过程    return instance;}

多线程可以安全的调用get_my_class_instance()①函数,不用为数据竞争而担心。

三. 使用 boost::shared_mutex 对数据结构进行保护

用 std::lock_guard<boost::shared_mutex> 和 std::unique_lock<boost::shared_mutex> 上锁。作为std::mutex 的替代方案,与 std::mutex 所做的一样,这就能保证升级线程的独占访问。由于其余线程不需要去修改数据结构,所以其可以使用 boost::shared_lock<boost::shared_mutex> 获取访问权。这与使用 std::unique_lock 一样,除非多线程要在同时获取同一个 boost::shared_mutex 上有共享锁。唯一的限制:当任一线程拥有一个共享锁时,这个线程就会尝试获取一个独占锁,直到其余线程放弃他们的锁;同样的,当任一线程拥有一个独占锁时,其余线程就无法取得共享锁或者独占锁,直到第一个线程放弃其拥有的锁。

使用 std::map 持有缓存数据,使用 boost::shared_mutex 进行保护。

#include <map>#include <string>#include <mutex>#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); //1        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); // 2        entries[domain]=dns_details;    }};

find_entry()使用 boost::shared_lock<> 来保护共享和只读权限①;这就使得多线程可以同时调用find_entry(),且不会出错。另一方面,update_or_add_entry()使用 std::lock_guard<> 实例,当表格需要升级时②,为其提供独占访问权限;update_or_add_entry()函数调用时,独占锁会阻止其余线程对数据结构进行修改,并且阻止线程调用find_entry()。

四. 嵌套锁

std::lock_guard<std::recursive_mutex> 和 std::unique_lock<std::recursive_mutex> 嵌套锁一般用在可并发访问的类上,所以其拥互斥量保护其成员数据。每个公共成员函数都会对互斥量上锁,而后完成对应的功能,之后再解锁互斥量。不过,有时成员函数会调用另一个成员函数,这种情况下,第二个成员函数也会试图锁住互斥量,这就会导致未定义行为的发生。“变通的”处理方案会将互斥量转为嵌套锁,第二个成员函数就能成功的进行上锁,并且函数能继续执行。但是,这样的使用方式是不推荐的,由于其过于草率,并且不正当。

说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » C++ 并发编程学习(九)

发表回复