理解 shared_ptr实现copy-on-write(COW)

本文介绍了如何使用C++中的shared_ptr实现Copy-On-Write技术,减少多线程环境下的锁竞争,提高程序效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

shared_ptr实现COW(Copy-On-Write)

前不久在《Linux多线程服务端编程使用muduoC++网络库》2.8节看到这个内容,一直没有真正理解,后来在书中7.3中再次提到使用shared_ptr实现copy-on-write的手法降低锁竞争,从shared_ptr的层面,彻底理解了一番。

之前copy-on-write详解分享中知道了其含义与过程,后又在StackOverFlow上学到了COW技术的精髓:

1.如果你是数据的唯一拥有者,那么你可以直接修改数据。
2.如果你不是数据的唯一拥有者,那么你拷贝它之后再修改。

用shared_ptr来实现COW时,主要考虑两点:
1.读数据
2.写数据

shared_ptr拥有对对象的引用计数,在对对象进行读写操作时,这个计数是1,当读数据时,我们创建一个新的智能指针指向原指针,这个时候引用计数加1。

//假设g_ptr是一个全局的shared_ptr<Foo>并且已经初始化。
void read()
{
    shared_ptr<Foo> tmpptr;
    {
        lock();
        tmpptr=g_ptr;//此时引用计数为2,通过gdb调试可以看到
    }
    //访问tmpptr
    //...
}

这部分是shared_ptr最基本的用法,还是很好理解的,read()函数调用结束,tmpptr作为栈上变量离开作用域,自然析构,原数据对象的引用计数也变为1。

写数据就复杂一些。根据COW的准则,当你是唯一拥有者(对应对象的引用计数是1)时,那么你直接修改数据,这样没有问题,当你不是唯一拥有者,则需要拷贝数据再去修改,这就需要用到一些shared_ptr的编程技法了:

void write()
{
    lock()
    if(!g_ptr.unique())
    {
        g_ptr.reset(new Foo(*g_ptr));
    }
    assert(g_ptr.unique());
    //write
    //
}

解释一下代码:
shared_ptr::unique(),当引用计数为1时返回true,否则false。
那么当引用计数不为1的时候,说明有别的线程正在读,受shread_ptr::reset()中example的误导,一直以为,reset后,原对象被析构,这样不就会影响正在读的线程了吗?

实际上:
假设一个线程读,一个线程写,当写线程进入到if循环中时,原对象的引用计数为2,分别为tmpptrg_ptr,此时reset()函数将原对象的引用计数减1,并且g_ptr已经指向了新的对象(用原对象构造),这样就完成了数据的拷贝,并且原对象还在,只是引用计数变成了1。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值