核心概念

设计上遵循以下原则:

1 不要在UI线程做不论什么堵塞式的I/O操作,以及其他耗时的操作,通过消息传递把各种操作传给相应用途的线程去做。

2 不鼓舞线程加锁机制和线程安全对象。

对象仅仅存在一个线程。通过消息来实现线程之间的通信,线程之间不互相堵塞。通过callback对象实现跨线程请求。

普通情况下,我们应该利用一个现有的线程,尽量不要创建新的线程。

UI线程实际上会被设置为不同意I/O操作。而且不同意等待。

线程列表

核心线程列表

所属进程 线程名称 类型 职责 实现
 Browser UI / BrowserThread Java Browser的主线程 content::BrowserThreadImpl
 Browser  Chrome_DBThread Native 负责数据库(SQLite)相关的操作,非常多功能的实现会用到该线程。

content::BrowserThreadImpl
 Browser  Chrome_FileThread Native 文件的创建、删除、读写等。 content::BrowserThreadImpl
 Browser  Chrome_FileUserBlockingThread Native 用于读取与用户交互有关的数据,须要高速的响应。看到net log模块和appcache实用。

content::BrowserThreadImpl
 Browser  Chrome_ProcessLauncherThread Native 用于启动和终止子进程。 content::BrowserThreadImpl
 Browser  Chrome_CacheThread Native    
        content::BrowserThreadImpl
 Browser  IndexedDB Native IndexDB存储线程。

base::Thread
GPU  Chrome_InProcGpuThread Native GPU的单进程版本号实现。 content::InProcessGpuThread
Child Processes Chrome_ChildIOThread Native 子进程的IO线程实现。

base::Thread
Renderer Chrome_InProcRendererThread Native Renderer进程的单进程版本号实现。

content::InProcessRendererThread

其他线程

线程名称 Module 实现 说明
CookieMonsterClient CAW base::Thread  
CookieMonsterBackend CAW base::Thread  
CookieSyncManager WebView Runnable  
Chrome_libJingle_WorkerThread Browser base::Thread  
Blink Heap Marker Thread (*) Blink base::Thread  
Blink GC Sweeper (*) Blink base::Thread  
HTMLParserThread Blink base::Thread  
AsyncTransferThread gpu gpu::TransferThread  
BrowserBlocking Worker Browser base::SequencedWorkerPool 详见:Chromium中应用C/C++并发技术要点
SimpleCache Worker net base::SequencedWorkerPool  
Network File Thread net base::Thread  

线程结构

(以单进程模型说明)

Android下线程的消息结构

Chromium的线程结构

各个类的职责说明:

职责说明
RunLoop

一个辅助类,主要封装消息循环 MessageLoop 类,其本
身没有特别的功能,主要提供一组公共接口被调用,其实质是调用 MessageLoop 类的接口和实现

MessageLoop

主消息循环,原理上讲,它应该能够处理三种类型的消息,包括支持不同平台的消息。

其实,假设让它处理全部这些消息,这会让其代码结构复杂不清难以理解。

消息循环仅仅须要三种类型:

  • 一种仅能处理自己定义任务
  • 一种能处理自己定义任务和 IO 操作
  • 一种是能处理自己定义任务和 UI 消息。

非常自然地,Chromium 定义一个基类 MessageLoop 用于处理自己定义任务,两个子类相应于第二和第三种类型。

对于第二和第三种 MessageLoop 类型,它们除了要处理任务外,还要处理平台相关的消息,为了结构清晰,
chromium 定义一个新的基类及其子类来负责处理它们,这就是 MessagePump。MessagePump 的每一个子类针对不同平台
和不同的消息类型。

MessagePump

一个抽象出来的基类,能够用来处理上面所列的第二和第三种消息类型。对于每一个平台,它们有不同的
MessagePump 的子类来相应,这些子类被包括在 MessageLoopForUI 和 MessageLoopForIO 类中。

摘自:<<理解WebKit和Chromium>>

Browser端线程结构

Browser端抛转线程消息,主要是基于BrowserThread提供的方法来完毕的,例如以下:

// 检測所在的线程
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
// 抛转任务到UI线程运行
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
        base::Bind(&AwLoginDelegate::HandleHttpAuthRequestOnUIThread,
                   this, (count->auth_attempts_ == 0)));
 
// 抛转任务到IO线程
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
      base::Bind(&AwLoginDelegate::ProceedOnIOThread,
                 this, user, password));

Render端的线程结构

Renderer端抛转消息,主要是基于MessageLoopProxy来完毕。例如以下:

base::Closure closure =
        base::Bind(&CompositorOutputSurface::ShortcutSwapAck,
                   weak_ptrs_.GetWeakPtr(),
                   output_surface_id_,
                   base::Passed(&frame->gl_frame_data),
                   base::Passed(&frame->software_frame_data));
base::MessageLoopProxy::current()->PostTask(FROM_HERE, closure);
 
// input_event_filter.cc中的演示样例
io_loop_->PostTask(FROM_HERE,
                     base::Bind(&InputEventFilter::SendMessageOnIOThread,
                                this,
                                base::Passed(&message)));
 
// Blink platform implemetation
base::MessageLoopProxy::current()->PostTask(
      FROM_HERE,
      base::Bind(&PlatformEventObserverBase::SendFakeDataForTesting,
                 base::Unretained(observer), data));

gpu与Browser/Renderer的交互


线程安全

对于Java及Android的线程安全不再展开。能够參考附件的资料:<<Efficient Android Threading Asynchronous Processing Techniques for Android Applications>>

关于Java则推荐《Java并发实战》。

最经常使用的形式,将使用的对象定义为base::RefCountedThreadSafe。保证引用的对象不会被提前析构。

对于一些非线程安全的类能够使用NonThreadSafe提供Debug模式下线程安全确认。也能够应用ThreadCollisionWarner/ThreadChecker 确保运行线程与设计一致。

详见:Chromium中应用C/C++并发技术要点

參考: 怎样安全的使用PostTask

任务的取消

除了任务按须要取消外,假设在宿主类析构后运行就可能导致崩溃。

眼下使用两种方式保证任务的取消:

WeakPtrFactory (WeakPtr)和CancelableTaskTracker, 它们析构时也会自己主动将任务取消。

CancelableTaskTracker能够參考Chromium官网的说明或是在FaviconCache中的应用。

class UserInputHandler : public base::RefCountedThreadSafe<UserInputHandler> {
  // Runs on UI thread.
  void OnUserInput(Input input) {
    CancelPreviousTask();
    DBResult* result = new DBResult();
    task_id_ = tracker_->PostTaskAndReply(
        BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB).get(),
        FROM_HERE,
        base::Bind(&LookupHistoryOnDBThread, this, input, result),
        base::Bind(&ShowHistoryOnUIThread, this, base::Owned(result)));
  }
 
  void CancelPreviousTask() {
    tracker_->TryCancel(task_id_);
  }
 
  ...
 
 private:
  CancelableTaskTracker tracker_;  // Cancels all pending tasks while destruction.
  CancelableTaskTracker::TaskId task_id_;
  ...
};

对于WeakPtr。Chromium已经封装了一个WeakptrFactory供使用。能够參考GpuBrowserCompositorOutputSurface中的使用。

使用方式比較简单。但没有CancelableTaskTracker通用。

以下是一个简单的演示样例(使用WeakPtrFactory<>最大的优点是不用改动类的定义.)

class MyObject {
 public:
  MyObject() : weak_factory_(this) {}
 
  void DoSomething() {
    const int kDelayMS = 100;
    MessageLoop::current()->PostDelayedTask(FROM_HERE,
        base::Bind(&MyObject::DoSomethingLater, weak_factory_.GetWeakPtr()),
        kDelayMS);
  }
 
  void DoSomethingLater() {
    ...
  }
 
 private:
  base::WeakPtrFactory<MyObject> weak_factory_;
};
*非线程安全,能够跨线程传递,但必须在一个线程上使用这个WeakPtr,即仅仅能在运行在同样线程的任务上使用这个机制。
*类中WeakPtrFactory<Foo> weak_factory_的成员须要放在全部其他成员的后面,确保其他成员的析构函数运行的时候WeakPtrs还是无效的。

关于WeakPtr的进一步解释能够參考: Chromium中的weak_ptr,以及 关于SupportWeakPtr与WeakPtrFactory的选择.

Chormium线程模型及应用指南的更多相关文章

  1. Netty IO线程模型学习总结

    Netty框架的 主要线程是IO线程.线程模型的好坏直接决定了系统的吞吐量.并发性和安全性. Netty的线程模型遵循了Reactor的基础线程模型.以下我们先一起看下该模型 Reactor线程模型 ...

  2. Netty 基本组件与线程模型

    Netty 的学习内容主要是围绕 TCP 和 Java NIO 这两个点展开的,由于 Netty 是基于 Java NIO 的 API 之上构建的网络通讯框架,Java NIO 中的几个组件,都能在 ...

  3. Netty系列之Netty线程模型

    Reference: http://www.infoq.com/cn/articles/netty-threading-model 1. 背景 1.1. Java线程模型的演进 1.1.1. 单线程 ...

  4. Dubbo入门到精通学习笔记(十一):Dubbo服务启动依赖检查、Dubbo负载均衡策略、Dubbo线程模型(结合Linux线程数限制配置的实战分享)

    文章目录 Dubbo服务启动依赖检查 Dubbo负载均衡策略 Dubbo线程模型(结合Linux线程数限制配置的实战分享) 实战经验分享( ** 属用性能调优**): Dubbo服务启动依赖检查 Du ...

  5. 看我是如何处理自定义线程模型---java

    看过我之前文章的园友可能知道我是做游戏开发,我的很多思路和出发点是按照游戏思路来处理的,所以和web的话可能会有冲突,不相符合. 来说说为啥我要自定义线程模型呢? 按照我做的mmorpg或者mmoar ...

  6. HBase的Write Ahead Log (WAL) —— 整体架构、线程模型

    解决的问题 HBase的Write Ahead Log (WAL)提供了一种高并发.持久化的日志保存与回放机制.每一个业务数据的写入操作(PUT / DELETE)执行前,都会记账在WAL中. 如果出 ...

  7. Netty学习三:线程模型

    1 Proactor和Reactor Proactor和Reactor是两种经典的多路复用I/O模型,主要用于在高并发.高吞吐量的环境中进行I/O处理. I/O多路复用机制都依赖于一个事件分发器,事件 ...

  8. Mina、Netty、Twisted一起学(十):线程模型

    要想开发一个高性能的TCP服务器,熟悉所使用框架的线程模型非常重要.MINA.Netty.Twisted本身都是高性能的网络框架,如果再搭配上高效率的代码,才能实现一个高大上的服务器.但是如果不了解它 ...

  9. WPF QuickStart系列之线程模型(Thread Model)

    这篇博客将介绍WPF中的线程模型. 首先我们先来看一个例子,用来计算一定范围内的素数个数. XAML: <Grid> <Grid.RowDefinitions> <Row ...

随机推荐

  1. C语言操作数截断

    //测试截断 #include <stdio.h> int main() { int a = 0x80000001; unsigned int b = 0x80000001; printf ...

  2. ArcGIS api for javascript——地图配置-定制导航箭头

    描述 本例展示了如何为平移地图包括自定义的按钮.地图被放置在一个宽3列和高3行的HTML表格的固定宽度中心单元.表格里剩余的单元放置标签为8个主要方向的缩写的按钮.每个按钮调用地图上不同的平移函数.例 ...

  3. javascript模拟类的最佳实践

    1:怎样模拟一个类 在sencha touch2 系列里面定义一个类和new出这个类的对象 Ext.define( "Animal", { config: { name: null ...

  4. 【POJ 2195】 Going Home(KM算法求最小权匹配)

    [POJ 2195] Going Home(KM算法求最小权匹配) Going Home Time Limit: 1000MS   Memory Limit: 65536K Total Submiss ...

  5. 关于android studio几种常见的错误解决

    我也是从ec转到as的,没办法,大势所趋嘛,然而,在使用as的过程中遇到了非常多匪夷所思的错误,如今就说一下今天我遇到的这个错误. 美工妹子给了我一张图片,用来当做button的背景图,当然,这个图也 ...

  6. CSS元素选择器 element selector(type selector)

    http://www.w3school.com.cn/css/css_selector_type.asp 元素选择器 最常见的 CSS 选择器是元素选择器.换句话说,文档的元素就是最基本的选择器. 如 ...

  7. spring mvc获取路径参数的几种方式

    一.从视图向controller传递值,  controller <--- 视图 1.通过@PathVariabl注解获取路径中传递参数 (参数会被复制到路径变量) @RequestMappin ...

  8. pig安装配置

    pig的安装配置很简单,只需要配置一下环境变量和指向hadoop conf的环境变量就行了 1.上传 2.解压 3.配置环境变量 Pig工作模式 本地模式:只需要配置PATH环境变量${PIG_HOM ...

  9. .Net Web开发技术栈 收藏

    原文:http://www.cnblogs.com/1996V/p/7700087.html#!comments 有很多朋友有的因为兴趣,有的因为生计而走向了.Net中,有很多朋友想学,但是又不知道怎 ...

  10. HTTP协议学习,post于get;用Fiddler测试请求

    转载 收藏于网络 1.简介: HTTP协议:Hypertext transfer protocol 超文本 传输 协议 它是TCP/IP协议集中的一个运用层协议. 用于定义WEB浏览器和WEB服务器之 ...