借shared_ptr实现写时复制(COW)
原理
1、使用智能指针管理共享资源
2、write端,若引用计数为1,则write端独占资源,若引用计数不为1,则对共享资源备份进行写操作,以确保线程安全
3、read端,读之前引用计数加1,write端此时若并发访问共享资源,则会发现引用计数不为1,write端不会直接写共享资源,确保线程安全
代码
#include <memory>
#include <vector>
#include <mutex>
// 共享资源
std::shared_ptr<std::vector<int>> g_vptr;
// 该互斥锁只用来保证访问shared_ptr时的线程安全
// 读写std::vector<int>的线程安全通过shared_ptr的引用计数保证
std::mutex g_mutex;
void read()
{
std::shared_ptr<std::vector<int>> vptr;
{
std::lock_guard<std::mutex> g(g_mutex);
vptr = g_vptr;
}
for(auto i : *vptr)
{
// read
}
}
void write(int data)
{
std::lock_guard<std::mutex> g(g_mutex);
if(!g_vptr.unique())
{
g_vptr.reset(new std::vector<int>(*g_vptr));
}
g_vptr->push_back(data);
}
代码释义
假设read
时开始了并发write
,read
后原对象引用计数为2,即vptr
和g_vptr
都指向原对象,write
时对g_vptr
进行reset
操作后,原对象引用计数减1,此时原对象引用计数为1,还不会被析构,只有vptr
指向原对象,而g_vptr
指向原对象的副本(一个新的对象),这样以来write
里对g_vptr
的写和read
里对vptr
的读不会相互影响。当read
里完成对vptr
的读,原对象引用计数减1,原对象引用计数为0,原对象析构,而write
里被修改的原对象副本此时已经成为新的原对象,后续读写都将基于这个新的原对象进行
参考
陈硕《Linux多线程服务端编程》