使用Mutex替换读写锁
在读《Linux多线程服务端编程》中第二章末尾的时候看到陈硕老师的分析,感觉写的很好,特此进行记录来加深印象
下面的链接是我看过的很好的博客
一个非常好的博客
背景:
多线程C++程序,24h * 5.5d运行。有多个工作线程处理客户的交易请求,有一个Background线程更新内部的数据,线程跟哈希表进行交互。工作线程只读,背景线程进行读写
要求:
这个系统对于读的要求比较敏感,而对于更新(背景线程)的要求不那么敏感,并且一天中更新的频率是很低的。下面使用mutex + shared_ptr降低延迟
主要的思想:
- 如果你是数据的唯一拥有者,那么你可以直接进行修改数据
- 如果你不是数据的唯一拥有者,那么你可以拷贝之后再进行修改
#include
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;
}