您的位置: 首页 > 技术文档 > 网络编程 > Chrome源码剖析
SQL Server2008 Resource Governor 回到列表 无缝的缓存读取:双存储缓存策略
 Chrome源码剖析

作者:duguguiyu 时间: 2009-04-02 文档类型:转载 来自:Venus神庙

第 1 页
第 2 页 Chrome的多线程模型 上
第 3 页 Chrome的多线程模型 下
第 4 页 Chrome的进程间通信 上
第 5 页 Chrome的多线程模型 中
第 6 页 Chrome的多线程模型 下
第 7 页 Chrome的进程模型
第 8 页 Chrome的UI绘制
第 9 页 Chrome的插件模型

2. Chrome中的Task

从上面的表不难看出,不论是哪一种消息循环,必须处理的,就是Task(暂且遗忘掉系统消息的处理和Watcher,以后,我们会缅怀它们的...)。刨去其它东西的干扰,只留下Task的话,我们可以这样认为:Chrome中的线程从实现层面来看没有任何区别,它的区别只存在于职责层面,不同职责的线程,会处理不同的Task。最后,在铺天盖地西红柿来临之前,我说一下啥是Task。。。

简单的看,Task就是一个类,一个包含了void Run()抽象方法的类(参见Task类...)。一个真实的任务,可以派生Task类,并实现其Run方法。每个MessagePump类中,会有一个MessagePump::Delegate的类的对象(MessagePump::Delegate的一个实现,请参见MessageLoop类...),在这个对象中,会维护若干个Task的队列。当你期望,你的一个逻辑在某个线程内执行的时候,你可以派生一个Task,把你的逻辑封装在Run方法中,然后实例一个对象,调用期望线程中的PostTask方法,将该Task对象放入到其Task队列中去,等待执行。我知道很多人已经抄起了板砖,因为这种手法实在是太常见了,就不是一个简单的依赖倒置,在线程池,Undo\Redo等模块的实现中,用的太多了。。。

但,我想说的是,虽说谁家过年都是吃顿饺子,这饺子好不好吃还是得看手艺,不能一概而论。在Chrome中,线程模型是统一且唯一的,这就相当于有了一套标准,它需要满足在各个线程上执行的几十上百种任务的需求,因此,必须在灵活行和易用性上有良好的表现,这就是设计标准的难度。为了满足这些需求,Chrome在底层库上做了足够的功夫:

  1. 它提供了一大套的模板封装(参见task.h),可以将Task摆脱继承结构、函数名、函数参数等限制(就是基于模板的伪function实现,想要更深入了解,建议直接看鼻祖《Modern C++》和它的Loki库...);
  2. 同时派生出CancelableTask、ReleaseTask、DeleteTask等子类,提供更为良好的默认实现;
  3. 在消息循环中,按逻辑的不同,将Task又分成即时处理的Task、延时处理的Task、Idle时处理的Task,满足不同场景的需求;
  4. Task派生自tracked_objects::Tracked,Tracked是为了实现多线程环境下的日志记录、统计等功能,使得Task天生就有良好的可调试性和可统计性;

这一套七荤八素的都搭建完,这才算是一个完整的Task模型,由此可知,这饺子,做的还是很费功夫的。。。

3. Chrome的多线程模型

工欲善其事,必先利其器。Chrome之所以费了老鼻子劲去磨底层框架这把刀,就是为了面对多线程这坨怪兽的时候杀的更顺畅一些。在Chrome的多线程模型下,加锁这个事情只发生在将Task放入某线程的任务队列中,其他对任何数据的操作都不需要加锁。当然,天下没有免费的午餐,为了合理传递Task,你需要了解每一个数据对象所管辖的线程,不过这个事情,与纷繁的加锁相比,真是小儿科了不知道多少倍。。。

图3 Task的执行模型

如果你熟悉设计模式,你会发现这是一个Command模式,将创建于执行的环境相分离,在一个线程中创建行为,在另一个线程中执行行为。Command模式的优点在于,将实现操作与构造操作解耦,这就避免了锁的问题,使得多线程与单线程编程模型统一起来,其次,Command还有一个优点,就是有利于命令的组合和扩展,在Chrome中,它有效统一了同步和异步处理的逻辑。。。

Command模式

Command模式,是一种看上去很酷的模式,传统的面向对象编程,我们封装的往往都是数据,在Command模式下,我们希望封装的是行为。这件事在函数式编程中很正常,封装一个函数作为参数,传来传去,稀疏平常的事儿;但在面向对象的编程中,我们需要通过继承、模板、函数指针等手法,才能将其实现。。。
应用Command模式,我们是期望这个行为能到一个不同于它出生的环境中去执行,简而言之,这是一种想生不想养的行为。我们做Undo/Redo的时候,会把在任一一个环境中创建的Command,放到一个队列环境中去,供统一的调度;在Chrome中,也是如此,我们在一个线程环境中创建了Task,却把它放到别的线程中去执行,这种寄居蟹似的生活方式,在很多场合都是有用武之地的。。。

在一般的多线程模型中,我们需要分清楚啥是同步啥是异步,在同步模式下,一切看上去和单线程没啥区别,但同时也丧失了多线程的优势(沦落成为多线程串行...)。而如果采用异步的模式,那写起来就麻烦多了,你需要注册回调,小心管理对象的生命周期,程序写出来是嗷嗷恶心。在Chrome的多线程模型下,同步和异步的编程模型区别就不复存在了,如果是这样一个场景:A线程需要B线程做一些事情,然后回到A线程继续做一些事情;在Chrome下你可以这样来做:生成一个Task,放到B线程的队列中,在该Task的Run方法最后,会生成另一个Task,这个Task会放回到A的线程队列,由A来执行。如此一来,同步异步,天下一统,都是Task传来传去,想不会,都难了。。。

图4 Chrome的一种异步执行的解决方案

4. Chrome多线程模型的优缺点

一直在说Chrome在规避锁的问题,那到底锁是哪里不好,犯了何等滔天罪责,落得如此人见人嫌恨不得先杀而后快的境地。《代码之美》的第二十四章“美丽的并发”中,Haskell设计人之一的Simon Peyton Jones总结了一下用锁的困难之处,我罚抄一遍,如下:

  1. 锁少加了,导致两个线程同时修改一个变量;
  2. 锁多加了,轻则妨碍并发,重则导致死锁;
  3. 锁加错了,由于锁和需要锁的数据之间的联系,只存在于程序员的大脑中,这种事情太容易发生了;
  4. 加锁的顺序错了,维护锁的顺序是一件困难而又容易出错的问题;
  5. 错误恢复;
  6. 忘记唤醒和错误的重试;
  7. 而最根本的缺陷,是锁和条件变量不支持模块化的编程。比如一个转账业务中,A账户扣了100元钱,B账户增加了100元,即使这两个动作单独用锁保护维持其正确性,你也不能将两个操作简单的串在一起完成一个转账操作,你必须让它们的锁都暴露出来,重新设计一番。好好的两个函数,愣是不能组在一起用,这就是锁的最大悲哀;

通过这些缺点的描述,也就可以明白Chrome多线程模型的优点。它解决了锁的最根本缺陷,即,支持模块化的编程,你只需要维护对象和线程之间的职能关系即可,这个摊子,比之锁的那个烂摊子,要简化了太多。对于程序员来说,负担一瞬间从泰山降成了鸿毛。。。
而Chrome多线程模型的一个主要难点,在于线程与数据关系的设计上,你需要良好的划分各个线程的职责,如果有一个线程所管辖的数据,几乎占据了大半部分的Task,那么它就会从多线程沦为单线程,Task队列的锁也将成为一个大大的瓶颈。。。

设计者的职责

一个底层结构设计是否成功,这个设计者是否称职,我一直觉得是有一个很简单的衡量标准的。你不需要看这个设计人用了多少NB的技术,你只需要关心,他的设计,是否给其他开发人员带来了困难。一个NB的设计,是将所有困难都集中在底层搞定,把其他开发人员换成白痴都可以工作的那种;一个SB的设计,是自己弄了半天,只是为了给其他开发人员一个长达250条的注意事项,然后很NB的说,你们按照这个手册去开发,就不会有问题了。。。

从根本上来说,Chrome的线程模型解决的是并发中的用户体验问题而不是联合工作的问题(参见我前面喷的“闲话并发”),它不是和Map/Reduce那样将关注点放在数据和执行步骤的拆分上,而是放在线程和数据的对应关系上,这是和浏览器的工作环境相匹配的。设计总是和所处的环境相互依赖的,毕竟,在客户端,不会和服务器一样,存在超规模的并发处理任务,而只是需要尽可能的改善用户体验,从这个角度来说,Chrome的多线程模型,至少看上去很美。。。

出处:Venus神庙
责任编辑:bluehearts

上一页 Chrome的多线程模型 上 下一页 Chrome的进程间通信 上

◎进入论坛网络编程版块参加讨论

相关文章
制作Google Chrome浏览器LOGO
web标准优秀源码下载
关键字搜索 常规搜索 推荐文档
热门搜索:CSS Fireworks 设计比赛 网页制作 web标准 用户体验 UE photoshop Dreamweaver Studio8 Flash 手绘 CG
站点最新 站点最新列表
周大福“敬•自然”设计大赛开启
国际体验设计大会7月将在京举行
中国国防科技信息中心标志征集
云计算如何让安全问题可控
云计算是多数企业唯一拥抱互联网的机会
阿里行云
云手机年终巨献,送礼标配299起
阿里巴巴CTO王坚的"云和互联网观"
1499元买真八核 云OS双蛋大促
首届COCO桌面手机主题设计大赛
栏目最新 栏目最新列表
浅谈JavaScript编程语言的编码规范
如何在illustrator中绘制台历
Ps简单绘制一个可爱的铅笔图标
数据同步算法研究
用ps作简单的作品展示页面
CSS定位机制之一:普通流
25个最佳最闪亮的Eclipse开发项目
Illustrator中制作针线缝制文字效果
Photoshop制作印刷凹凸字体
VS2010中创建自定义SQL Rule
>> 分页 首页 前页 后页 尾页 页次:3/91个记录/页 转到 页 共9个记录

蓝色理想版权申明:除部分特别声明不要转载,或者授权我站独家播发的文章外,大家可以自由转载我站点的原创文章,但原作者和来自我站的链接必须保留(非我站原创的,按照原来自一节,自行链接)。文章版权归我站和作者共有。

转载要求:转载之图片、文件,链接请不要盗链到本站,且不准打上各自站点的水印,亦不能抹去我站点水印。

特别注意:本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有,文章若有侵犯作者版权,请与我们联系,我们将立即删除修改。

您的评论
用户名:  口令:
说明:输入正确的用户名和密码才能参与评论。如果您不是本站会员,你可以注册 为本站会员。
注意:文章中的链接、内容等需要修改的错误,请用报告错误,以利文档及时修改。
不评分 1 2 3 4 5
注意:请不要在评论中含与内容无关的广告链接,违者封ID
请您注意:
·不良评论请用报告管理员,以利管理员及时删除。
·尊重网上道德,遵守中华人民共和国的各项有关法律法规
·承担一切因您的行为而直接或间接导致的民事或刑事法律责任
·本站评论管理人员有权保留或删除其管辖评论中的任意内容
·您在本站发表的作品,本站有权在网站内转载或引用
·参与本评论即表明您已经阅读并接受上述条款
推荐文档 | 打印文档 | 评论文档 | 报告错误  
专业书推荐 更多内容
网站可用性测试及优化指南
《写给大家看的色彩书1》
《跟我去香港》
众妙之门—网站UI 设计之道
《Flex 4.0 RIA开发宝典》
《赢在设计》
犀利开发—jQuery内核详解与实践
作品集 更多内容

杂⑦杂⑧ Gold NORMANA V2