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

转自:http://blog.csdn.net/zhangxiao93/article/details/52792888

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//...
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

这部分是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//
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

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

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


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/509231.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

window连接不上ssdb的问题

window上访问虚拟机ssdb 1&#xff09;首先要修改ssdb 的配置文件ssdb.conf&#xff0c;修改server的节点下ip如下&#xff1a; server节点下的ip意思是绑定哪个ip地址能够访问服务 &#xff0c;也就是说只能通过的ip可以访问ssdb server。 ps&#xff1a; 127.0.0.1 //绑定…

分布式系统的工程化开发方法

转自&#xff1a;http://blog.csdn.net/solstice/article/details/5950190 以下是我在珠三角技术沙龙 2010Q4 上的演讲投影片。 演讲视频&#xff1a; http://www.youku.com/playlist_show/id_5238686.html ---------- ---------- ------

java操作ssdb:set、map、list..

网上收集的代码模板&#xff1a; import com.udpwork.ssdb.*;/** * SSDB Java client SDK demo. */ public class Demo { public static void main(String[] args) throws Exception { SSDB ssdb null; Response resp; byte[] b; ssdb new SSDB("127.0.0.1", 8888…

程序员的知识广度

转自&#xff1a;http://blog.csdn.net/EGEFCXzo3Ha1x4/article/details/79070190 “知识变现”的口号一喊 确实让很多人都摩拳擦掌蓄势待发 那么作为程序员的mu们 不管是思维逻辑&#xff0c;还是知识广度 是不是都迫不及待了 今天&#xff0c;我们也来测试下 【单选题】 1 …

【转载】RocketMQ优秀文章

rocketMq详解&#xff1a;http://blog.csdn.net/column/details/learningrocketmq.html rocketMq实践&#xff1a;https://pan.baidu.com/s/1kTXE4PD rocketMq的原理&#xff1a;https://pan.baidu.com/s/1bogcpgN rocketMq用户指南&#xff1a;https://pan.baidu.com/s/1kT…

多线程---条件变量

互斥器和条件变量的区别&#xff1a;互斥器具有加锁原语&#xff0c;用来进行排他性的访问共享数据&#xff0c;而条件变量具有等待原语&#xff0c;用于等待某个事件的发生。 等待条件变量的正确姿势&#xff1a; void wait() {mutex.lock()while (wait_flag false) {conditi…

ngnix安装

一、安装Nginx&#xff1a; 1 : wget下载: http://nginx.org/download/nginx-1.4.2.tar.gz 2 : 进行安装&#xff1a; tar -zxvf nginx-1.6.2.tar.gz 3 : 下载锁需要的依赖库文件&#xff1a; yum install pcre yum install pcre-devel yum install zlib yum install zl…

ARP-地址解析协议(在实践中深入理解ARP协议)

在同一个网络&#xff08;无特别说明&#xff0c;均指以太网络&#xff09;中进行通信的主机&#xff0c;必须要拥有目标主机的MAC地址才能够正确地将数据发送给目标主机&#xff0c;那么如何知道目标主机的MAC地址呢&#xff1f;可以通过ARP协议。ARP协议就是用来获取目标IP地…

Maven私服

1 Maven私服简介 Maven 私服是一种特殊的Maven远程仓库&#xff0c;它是架设在局域网内的仓库服务&#xff0c;用来代理位于外部的远程仓库&#xff08;中央仓库、其他远程公共仓库&#xff09;。 1.1 下载构件顺序 建立私服后&#xff0c;当局域网内的用户需要某个构件时&a…

nginx配置文件中参数的作用

####默认的nobody&#xff0c;没有访问目录权限&#xff0c;然后指定有权限的用户 ####user nobody; ####一般一个进程足够了&#xff0c;你可以把连接数设得很大。 ####如果有SSL、gzip这些比较消耗CPU的工作&#xff0c;而且是多核CPU的话&#xff0c;可以设为和CPU的数量一…

TCP/IP协议--ARP协议(有了IP地址为什么还需要ARP协议)

首先我们需要先大致了解一下MAC地址&#xff0c;MAC&#xff08;Media Access Control, 介质访问控制&#xff09;地址是烧录在Network Interface Card(网卡,NIC)里的,也叫硬件地址,是由48比特长(6字节),16进制的数字组成.0-23位叫做组织唯一标志符(organizationally unique &a…

Unity3d--跨平台(一)

转自&#xff1a;https://www.cnblogs.com/murongxiaopifu/p/4211964.html前言&#xff1a; 其实小匹夫在U3D的开发中一直对U3D的跨平台能力很好奇。到底是什么原理使得U3D可以跨平台呢&#xff1f;后来发现了Mono的作用&#xff0c;并进一步了解到了CIL的存在。所以&#xff0…

linux定时任务的用法详解

crontab的基本格式&#xff1a; f1  f2  f3  f4  f5  command 分  时 日  月  周  命令 第一列f1代表分钟1~59&#xff1a;当f1为表示每分钟都要执行&#xff1b;为/n表示每n分钟执行一次&#xff1b;为a-b表示从第a分钟到第b分钟这段时间要执行&#xff1b;为a,…

Unity3d-跨平台(二)

转自&#xff1a;http://www.jiandaima.com/blog/archives/945.html 是如何输出到多平台的&#xff1f; 我的第一篇文章&#xff0c;选择了一个不那么简单的主题&#xff0c;但是是我近期比较感兴趣的。这周&#xff0c;我和一个朋友&#xff0c;谈到了游戏开发和Unity3D&#…

lua的作用

轻量级: 它用标准C语言编写并以源代码形式开放&#xff0c;编译后仅仅一百余K&#xff0c;可以很方便的嵌入别的程序里。 可扩展: Lua提供了非常易于使用的扩展接口和机制&#xff1a;由宿主语言(通常是C或C)提供这些功能&#xff0c;Lua可以使用它们&#xff0c;就像是本来就内…

Almost Arithmetical Progression

Description Gena loves sequences of numbers. Recently, he has discovered a new type of sequences which he called an almost arithmetical progression. A sequence is an almost arithmetical progression, if its elements can be represented as: a1  p, where p i…

svn冲突解决方案

解决方法 步骤一、清空svn的队列 1、进入到项目的.svn目录中&#xff0c;查看是否存在wc.db文件 C:\Users\Administrator>D:D:\>cd D:\BBK_SVN\I3_TrunkD:\BBK_SVN\I3_Trunk>cd .svnD:\BBK_SVN\I3_Trunk\.svn>dirVolume in drive D has no label.Volume Serial Nu…

redis集群搭建与配置

redis集群搭建与配置

VS编译快捷键设置

1.编译当前文件----AltZ(生成.编译)&#xff1b; 2.编译当前项目----AltA(生成.仅生成项目)&#xff1b; 3.链接当前项目----AltX(生成.链接)&#xff1b; 4.生成选定内容----AltD(生成.生成选定内容)&#xff1b;

keepalived的安装与添加服务

keepalived的安装与添加服务