Mutex和智能指针替代读写锁

4 篇文章 0 订阅
使用Mutex替换读写锁

在读《Linux多线程服务端编程》中第二章末尾的时候看到陈硕老师的分析,感觉写的很好,特此进行记录来加深印象
下面的链接🔗是我看过的很好的博客
一个非常好的博客

背景:

多线程C++程序,24h * 5.5d运行。有多个工作线程处理客户的交易请求,有一个Background线程更新内部的数据,线程跟哈希表进行交互。工作线程只读,背景线程进行读写

要求:

这个系统对于读的要求比较敏感,而对于更新(背景线程)的要求不那么敏感,并且一天中更新的频率是很低的。下面使用mutex + shared_ptr降低延迟

主要的思想:
  • 如果你是数据的唯一拥有者,那么你可以直接进行修改数据
  • 如果你不是数据的唯一拥有者,那么你可以拷贝之后再进行修改
#include <map>
#include <string>
#include <vector>

#include <boost/shared_ptr.hpp>

#include "../Mutex.h"

using std::string;

class CustomerData : boost::noncopyable
{
 public:
  CustomerData()
    : data_(new Map)
  { }

  int query(const string& customer, const string& stock) const;

 private:
  typedef std::pair<string, int> Entry;
  typedef std::vector<Entry> EntryList;
  typedef std::map<string, EntryList> Map;
  typedef boost::shared_ptr<Map> MapPtr;
  void update(const string& customer, const EntryList& entries);
  void update(const string& message);

  static int findEntry(const EntryList& entries, const string& stock);
  static MapPtr parseData(const string& message);

  MapPtr getData() const
  {
    muduo::MutexLockGuard lock(mutex_);
    return data_;
  }

  mutable muduo::MutexLock mutex_;
  MapPtr data_;
};

int CustomerData::query(const string& customer, const string& stock) const
{
  MapPtr data = getData();

  Map::const_iterator entries = data->find(customer);
  if (entries != data->end())
    return findEntry(entries->second, stock);
  else
    return -1;
}

void CustomerData::update(const string& customer, const EntryList& entries)
{
  muduo::MutexLockGuard lock(mutex_);
  if (!data_.unique())
  {
    MapPtr newData(new Map(*data_));
    data_.swap(newData);
  }
  assert(data_.unique());
  (*data_)[customer] = entries;
}

void CustomerData::update(const string& message)
{
  MapPtr newData = parseData(message);
  if (newData)
  {
    muduo::MutexLockGuard lock(mutex_);
    data_.swap(newData);
  }
}

int main()
{
  CustomerData data;
}
Read

在本样例中体现的就是函数query

int CustomerData::query(const string& customer, const string& stock) const
{
  MapPtr data = getData();

  Map::const_iterator entries = data->find(customer);
  if (entries != data->end())
    return findEntry(entries->second, stock);
  else
    return -1;
}

对于哈希表来说(这个操作只是读,并没有修改这个map的内容),因此我们复制一下map, 用局部变量MapPtr data持有map, 防止并发修改

注意我们并没有进行互斥手段,其实互斥手段在getData()中,拿到shared_ptr,之后就不需要访问原有的智能指针了

Write

关键就是看update, 更新数据那么要加锁,并且是 **全程加锁 **。

  • 如果这时候其他线程在读取,那么不能修改原来的部分,需要复制一个副本进行修改,然后替换
  • 如果没有用户在读取,所以是写线程单独持有,直接进行修改就好了
void CustomerData::update(const string& customer, const EntryList& entries)
{
  muduo::MutexLockGuard lock(mutex_);
  if (!data_.unique())
  {
    MapPtr newData(new Map(*data_));
    data_.swap(newData);
  }
  assert(data_.unique());
  (*data_)[customer] = entries;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值