Chormium執行緒模型及應用指南
核心概念
設計上遵循以下原則:
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 型別,它們除了要處理任務外,還要處理平臺相關的訊息,為了結構清晰, |
MessagePump | 一個抽象出來的基類,可以用來處理上面所列的第二和第三種訊息型別。對於每個平臺,它們有不同的 |
摘自:<<理解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 確保執行執行緒與設計一致。
參考: 如何安全的使用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的選擇.
相關文章
- 執行緒模型執行緒模型
- Reactor執行緒模型及其在Netty中的應用React執行緒模型Netty
- Dubbo執行緒模型執行緒模型
- WPF執行緒模型執行緒模型
- 常用高併發網路執行緒模型設計及mongodb執行緒模型優化實踐執行緒模型MongoDB優化
- 執行緒同步及執行緒鎖執行緒
- osi7層模型及執行緒和程式模型執行緒
- Redis 網路架構及單執行緒模型Redis架構執行緒模型
- 執行緒的建立及執行緒池執行緒
- Python執行緒指南Python執行緒
- Redis的執行緒模型Redis執行緒模型
- Dubbo的執行緒模型執行緒模型
- 程式和執行緒模型執行緒模型
- webrtc執行緒模型分析Web執行緒模型
- 理解 RxJava 執行緒模型RxJava執行緒模型
- RxJava 執行緒模型分析RxJava執行緒模型
- Netty執行緒模型Netty執行緒模型
- memcache的執行緒模型執行緒模型
- 聊聊執行緒技術與執行緒實現模型執行緒模型
- 【原創】Java多執行緒初學者指南(2):用Thread類建立執行緒Java執行緒thread
- 多執行緒和多程式模型的選用執行緒模型
- ObjC 多執行緒簡析(一)-多執行緒簡述和執行緒鎖的基本應用OBJ執行緒
- Posix執行緒程式設計指南(3)-執行緒同步 (轉)執行緒程式設計
- 淺談linux執行緒模型和執行緒切換Linux執行緒模型
- Android執行緒管理之ThreadLocal理解及應用場景Android執行緒thread
- Android中子執行緒更新主執行緒UI和ProgressBar的應用Android執行緒UI
- 多執行緒之共享模型執行緒模型
- 執行緒池執行模型原始碼全解析執行緒模型原始碼
- Posix執行緒程式設計指南(4)-執行緒終止 (轉)執行緒程式設計
- 淺談執行緒池(上):執行緒池的作用及CLR執行緒池執行緒
- 小度分享-【多執行緒工作及執行緒安全】執行緒
- 多執行緒之間通訊及執行緒池執行緒
- 玩轉java多執行緒 之多執行緒基礎 執行緒狀態 及執行緒停止實戰Java執行緒
- mongodb核心原始碼實現及效能最佳化:常用高併發執行緒模型設計及mongodb執行緒模型最佳化實踐MongoDB原始碼執行緒模型
- 多執行緒應用初探(一)----(概念,安全)執行緒
- iOS中多執行緒之GCD應用iOS執行緒GC
- Java 多執行緒應用 之 ArrayBlockingQueueJava執行緒BloC
- Spring Boot執行緒安全指南Spring Boot執行緒