现在的位置: 首页 > 综合 > 正文

chromium学习:thread

2013年09月25日 ⁄ 综合 ⁄ 共 2469字 ⁄ 字号 评论关闭

        在前面,我们学习了content_shell的流程,串成了一条执行线。从今天开始,我们要开始学习线上的点,由点延伸成为面,最后组成一个学习chromium的网。

        

        首先,我们先介绍chromium中的thread相关知识。

         

          chromium中有哪些线程呢?

          1. UI线程。应用程序起来后的主线程。

          2. IO线程。负责browser进程和子进程之间的调度线程

          3. file线程。不解释

          4. db线程。不解释

          5. safe_browsing线程。不清楚

         chromium关于thread的设计原则有两个:1. 不阻塞UI线程,使得UI有更好的响应。2.不鼓励加锁机制和线程安全对象。

        

         如何做到的呢?那就要考虑chromium中的线程模型了。


         1. 不在UI线程作阻塞IO操作,不在IO线程作阻塞IO操作。


         2. 线程之间不互相阻塞


         3. 许多API都是异步的


         为了避免加锁机制,chromium提供的thread模型是在每个线程内保留消息循环,线程之间通过消息传递任务,处理回调函数。

       

        关于多线程的加锁,摘抄如下一段话

多线程编程一直是一件麻烦的事情,线程执行的不确定性,资源的并发访问,一直困扰着众多程序员们。为了解决多线程编程的麻烦,大家想出了很多经典的方案:如:对资源直接加锁,角色模型,CSP,FP等等。他们的思想基本分为两类:一类是对存在并发访问资源直接加锁,第二类是避免资源被并发访问。前者存在许多问题,如死锁,优先级反转等等,而相对来说,后者会好很多,角色模型,CSP和FP就都属于后者,Chrome也是使用后者的思想来实现多线程的。

         从开发的角度,我们该如何使用chromium提供的这种线程模型呢?

         

         提供模板base::Callback<>,该类有一个Run函数。其作为函数指针泛型,由base::Bind产生。废话少说,看个例子就什么都明白了


void ReadToString(const std::string& filename, const base::Callback<void(const std::string&)>& on_read);

void DisplayString(const std::string& result) {
  LOG(INFO) << result;
}

void SomeFunc(const std::string& file) {
  ReadToString(file, base::Bind(&DisplayString));
};

        解释:base::Bind把函数指针 &DisplayString 转化为 base::Callback<void(const std::string& result)>。参数部分请参考
柯里化 


        如何往一个线程里面放任务呢?


        chromium提供的线程模型里面提供PostTask,PostDelayedTask方法。我们以PostTask为例。

void MessageLoop::PostTask(
    const tracked_objects::Location& from_here, const base::Closure& task)
其中,
typedef Callback<void(void)> Closure;

        因此,可以看到如下一个简单的例子

void WriteToFile(const std::string& filename, const std::string& data);
BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
                        base::Bind(&WriteToFile, "foo.txt", "hello world!"));

        如何让一个类成员函数作为task呢?


        同样的道理,只是第一个参数变为类对象。如下例子,不过注意对象通常是引用计数的。

class MyObject : public base::RefCountedThreadSafe<MyObject> {
 public:
  void DoSomething(const std::string16& name) {
    thread_->message_loop()->PostTask(
       FROM_HERE, base::Bind(&MyObject::DoSomethingOnAnotherThread, this, name));
  }

  void DoSomethingOnAnotherThread(const std::string16& name) {
    ...
  }
 private:
  // Always good form to make the destructor private so that only RefCountedThreadSafe can access it.
  // This avoids bugs with double deletes.
  friend class base::RefCountedThreadSafe<MyObject>;

  ~MyObject();
  Thread* thread_;
};

        注意:base::bind中的参数会被复制到内部存储结构。


       未完成,继续!!!


        以下的参考很不错。第一个是我本文的主要来源,或者说翻译了部分精华内容。第二个从源码的角度分析了thread。第三个就从实现的角度讲解。


参考:


1. http://www.chromium.org/developers/design-documents/threading


2. http://0xffff.me/2011/12/30/%E9%97%B2%E8%AF%9Dchromium%E7%9A%84%E7%BA%BF%E7%A8%8B%E6%A8%A1%E5%9E%8B.html


3. http://bigasp.com/archives/478

抱歉!评论已关闭.