Chromium源码浅析---单例模式(Singleton Pattern)在Chromium中的应用

本文探讨Chromium源码中单例模式的使用,特别是如何在BrowserMainLoop类中实现单例,以确保Browser进程中的唯一实例,如AudioManager和MediaStreamManager。单例模式通过全局变量控制实例创建,并限制GetInstance方法在UI线程中调用,以解决多线程同步问题。

[本文属原创,如有转载,请注明出处http://blog.csdn.net/yl02520/article/]

单例模式是一种常见的软件设计模式,该模式设计的目的是只允许系统中出现一个该类的实例。在Chromium的多进程架构中,有且只有一个Browser进程,所有的Renderer进程都与Browser进程通信,共享Browser进程中的资源,为了保证每个Renderer进程获取资源的统一性,所以在Browser进程引用了大量的单例模式来设计资源类,例如AudioManager,BrowserMainLoop等。

首先简单介绍一下单例模式

public class Singleton {
  private static Singleton instance; 
  private Singleton (){}  
  public static Singleton getInstance() { 
    if (instance == null) { 
      instance = new Singleton(); 
    } 
    return instance; 
  } 
}

上例是一个简单的java代码,在类Singleton没有公有的构造函数,也就是说不允许通过new操作符来申请一个该对象的实例,必须通过类的静态方法Singleton::getInstance()来获取,当该函数第一次被调用时就申请一个实例,以后每次访问时,就直接返回之前以申请好的实例,这就保证了在系统中保持该类的唯一实例。细心的朋友可能会问,在多线程中该单例模式的实现也能有效吗?这是一个好问题,答案是不能,如果是多线程访问的话,就需要在方法getInstance()中加入互斥操作。本文就不对单例模式的实现加以展开,如有兴趣可以参考弗里曼编写的《Head First设计模式》一书,里面对单例模式的实现方式有深入讨论。

下面以BrowserMainLoop为例介绍一下单例模式在Chromium中的应用。

BrowserMainLoop类的实例存在于Broswer进程中,它负责Browser进程启动的初始化,关闭时的对象释放与回收,以及整个Browser进程中主线程的消息循环,另外在BrowserMainLoop中保存在AudioManager,MediaStreamManager等只允许单一实例的对象,所以在Browser进程中只允许存在BrowserMainLoop的一个实例,这里就正好采用单例模式来设计。

关于BrowserMainLoop的代码片段如下:  

BrowserMainLoop* g_current_browser_main_loop = NULL;
class CONTENT_EXPORT BrowserMainLoop {
public:
  static BrowserMainLoop* GetInstance() {
    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); //确保只能在UI线程中访问,避免了多线程访问引起的同步问题。
    return g_current_browser_main_loop;
  }
  BrowserMainLoop::BrowserMainLoop(…){
    DCHECK(!g_current_browser_main_loop); //确保当前没有BrowserMainLoop的实例。
    g_current_browser_main_loop = this;
  }
  BrowserMainLoop::~BrowserMainLoop() {
    DCHECK_EQ(this, g_current_browser_main_loop);//确保当前只有一个实例。
    g_current_browser_main_loop = NULL;
  }
  ……
};

这个单例模式的实现与传统的实现方式有所区别,它并没有把构造函数设置成私有的,而是通过一个全局变量的方式来控制当前值允许只有一个实例,从源码的注释可知,如果通过两次new操作去创建该类的实例时,就会在构造函数中断言失败,这足以让开发者知道错误而去改进代码。代码没有在GetInstance中去申请对象,也就省略了判断当前实例是否为空等语句,让执行效率更高。另外,GetInstance方法只允许在UI线程中访问,也就避免了多线程访问的同步问题。如果其它线程需要访问该实例该怎么办呢?这就需要申请一个新的任务添加到UI线程的任务队列中,让UI线程依次处理,详情可参见本博客的另外一篇博文《Chromium的多线程机制》http://blog.csdn.net/yl02520/article/details/17007933

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值